PageRenderTime 39ms CodeModel.GetById 2ms app.highlight 29ms RepoModel.GetById 2ms app.codeStats 0ms

/qeephp/library/core/context.php

http://enaj.googlecode.com/
PHP | 1395 lines | 694 code | 79 blank | 622 comment | 75 complexity | 882684c911cca8b709611ad6c51d69fe MD5 | raw file
   1<?php
   2// $Id: context.php 2421 2009-04-14 08:59:23Z jerry $
   3
   4/**
   5 * ?? QContext ?
   6 *
   7 * @link http://qeephp.com/
   8 * @copyright Copyright (c) 2006-2009 Qeeyuan Inc. {@link http://www.qeeyuan.com}
   9 * @license New BSD License {@link http://qeephp.com/license/}
  10 * @version $Id: context.php 2421 2009-04-14 08:59:23Z jerry $
  11 * @package core
  12 */
  13
  14/**
  15 * QContext ?????????
  16 *
  17 * ?????????? QeePHP ????????????
  18 * QContext ????????????????? URL ??????
  19 *
  20 * QContext ???????????????? QContext::instance() ???
  21 * QContext ????????
  22 *
  23 * QContext ??? ArrayAccess ?????? QContext ???????????
  24 *
  25 * @code php
  26 * if (isset($context['title']))
  27 * {
  28 *     echo $context['title'];
  29 * }
  30 * @endcode
  31 *
  32 * @author YuLei Liao <liaoyulei@qeeyuan.com>
  33 * @version $Id: context.php 2421 2009-04-14 08:59:23Z jerry $
  34 * @package core
  35 */
  36class QContext implements ArrayAccess
  37{
  38    /**
  39     * ?? UDI ????
  40     */
  41    // UDI ??????
  42    const UDI_ALL        = 'all';
  43    // UDI ?????
  44    const UDI_CONTROLLER = 'controller';
  45    // UDI ????
  46    const UDI_ACTION     = 'action';
  47    // UDI ??????
  48    const UDI_NAMESPACE  = 'namespace';
  49    // UDI ????
  50    const UDI_MODULE     = 'module';
  51
  52    /**
  53     * ?? UDI ????
  54     */
  55    // ?????
  56    const UDI_DEFAULT_CONTROLLER = 'default';
  57    // ????
  58    const UDI_DEFAULT_ACTION     = 'index';
  59    // ?????
  60    const UDI_DEFAULT_MODULE     = 'default';
  61    // ???????
  62    const UDI_DEFAULT_NAMESPACE  = 'default';
  63
  64    /**
  65     * ?? URL ??
  66     */
  67    // ?? URL ??
  68    const URL_MODE_STANDARD = 'standard';
  69    // ?? PATHINFO
  70    const URL_MODE_PATHINFO = 'pathinfo';
  71    // ?? URL ??
  72    const URL_MODE_REWRITE  = 'rewrite';
  73
  74    /**
  75     * ????????
  76     *
  77     * ???????$module_name ???? public ?????
  78     * ???????? changeRequestUDI() ????? $module_name ????
  79     *
  80     * @var string
  81     */
  82    public $module_name;
  83
  84    /**
  85     * ?????????
  86     *
  87     * @var string
  88     */
  89    public $namespace;
  90
  91    /**
  92     * ??????????
  93     *
  94     * @var string
  95     */
  96    public $controller_name;
  97
  98    /**
  99     * ????????
 100     *
 101     * @var string
 102     */
 103    public $action_name;
 104
 105    /**
 106     * ?????
 107     *
 108     * @var array
 109     */
 110    private $_params = array();
 111
 112    /**
 113     * ????
 114     *
 115     * @var QRouter
 116     */
 117    private $_router;
 118
 119    /**
 120     * ???? URL
 121     *
 122     * @var string
 123     */
 124    static private $_request_uri;
 125
 126    /**
 127     * ???? URL ??????????
 128     *
 129     * @var string
 130     */
 131    static private $_base_uri;
 132
 133    /**
 134     * ???? URL ?????
 135     *
 136     * @var string
 137     */
 138    static private $_base_dir;
 139
 140    /**
 141     * ????
 142     *
 143     * @var string
 144     */
 145    static private $_url_mode;
 146
 147    /**
 148     * UDI ????
 149     */
 150    private static $_udi_defaults = array(
 151        self::UDI_MODULE => self::UDI_DEFAULT_MODULE,
 152        self::UDI_NAMESPACE => self::UDI_DEFAULT_NAMESPACE,
 153        self::UDI_CONTROLLER => self::UDI_DEFAULT_CONTROLLER,
 154        self::UDI_ACTION     => self::UDI_DEFAULT_ACTION,
 155    );
 156
 157    /**
 158     * ????
 159     */
 160    private function __construct()
 161    {
 162        $this->reinit();
 163    }
 164
 165    /**
 166     * ??????????????? QContext ??
 167     *
 168     * @param boolean $full_init ??????????
 169     */
 170    function reinit($full_init = false)
 171    {
 172        if ($full_init)
 173        {
 174            $this->_params = array();
 175            $this->_router = null;
 176        }
 177
 178        self::$_request_uri = null;
 179        self::$_base_uri    = null;
 180        self::$_base_dir    = null;
 181        self::$_url_mode    = null;
 182
 183        // ?????????????
 184        $url_mode = strtolower(Q::ini('dispatcher_url_mode'));
 185        if (is_null($this->_router)
 186            && ($url_mode == self::URL_MODE_PATHINFO || $url_mode == self::URL_MODE_REWRITE))
 187        {
 188            $this->_router = new QRouter();
 189            $this->_router->import(Q::ini('routes'), 'global_default_routes');
 190            $result = $this->_router->match('/' . ltrim($this->pathinfo(), '/'));
 191            if ($result)
 192            {
 193                foreach ($result as $var => $value)
 194                {
 195                    if (empty($value) && $value !== '0') continue;
 196                    if (empty($_GET[$var]))
 197                    {
 198                        $_GET[$var] = $_REQUEST[$var] = $value;
 199                    }
 200                }
 201            }
 202        }
 203        self::$_url_mode = $url_mode;
 204
 205        // ? $_GET ???????
 206        $keys = array_keys($_GET);
 207        if (!empty($keys))
 208        {
 209            $keys = array_combine($keys, $keys);
 210            $keys = array_change_key_case($keys);
 211        }
 212
 213        $udi = array();
 214        $udi[self::UDI_CONTROLLER] = (isset($keys[self::UDI_CONTROLLER]))
 215                                     ? $_GET[$keys[self::UDI_CONTROLLER]] : null;
 216        $udi[self::UDI_ACTION]     = (isset($keys[self::UDI_ACTION]))
 217                                     ? $_GET[$keys[self::UDI_ACTION]] : null;
 218        $udi[self::UDI_MODULE]     = (isset($keys[self::UDI_MODULE]))
 219                                     ? $_GET[$keys[self::UDI_MODULE]] : null;
 220        $udi[self::UDI_NAMESPACE]  = (isset($keys[self::UDI_NAMESPACE]))
 221                                     ? $_GET[$keys[self::UDI_NAMESPACE]] : null;
 222        $this->changeRequestUDI($udi);
 223    }
 224
 225    /**
 226     * ?? QContext ???????
 227     *
 228     * @code php
 229     * $context = QContext::instance();
 230     * @endcode
 231     *
 232     * @return QContext QContext ???????
 233     */
 234    static function instance()
 235    {
 236        static $instance;
 237        if (is_null($instance)) $instance = new QContext();
 238        return $instance;
 239    }
 240
 241    /**
 242     * ???????????
 243     *
 244     * __get() ??????????? $context->parameter ??????????
 245     * ?????????????? null?
 246     *
 247     * @code php
 248     * $title = $context->title;
 249     * @endcode
 250     *
 251     * ?????????? $_GET?$_POST ? QContext ???????
 252     *
 253     * @param string $parameter ????????
 254     *
 255     * @return mixed ???
 256     */
 257    function __get($parameter)
 258    {
 259        return $this->query($parameter);
 260    }
 261
 262    /**
 263     * ???????????
 264     *
 265     * ? __get() ???????__set() ???? QContext ???????
 266     * ??? $_GET ? $_POST ?????????? __set() ??????
 267     * ???? QContext::param() ??????
 268     *
 269     * @code php
 270     * $context->title = $title;
 271     * echo $context->param('title');
 272     * @endcode
 273     *
 274     * @param string $parameter ????????
 275     * @param mixed $value ???
 276     */
 277    function __set($parameter, $value)
 278    {
 279        $this->changeParam($parameter, $value);
 280    }
 281
 282    /**
 283     * ????????????????
 284     *
 285     * @param string $parameter ??????
 286     *
 287     * @return boolean ????????
 288     */
 289    function __isset($parameter)
 290    {
 291        return $this->offsetExists($parameter);
 292    }
 293
 294    /**
 295     * ?????????
 296     *
 297     * __unset() ??????? QContext ????????
 298     *
 299     * @code php
 300     * unset($context['title']);
 301     * // ???? title ??????? null
 302     * echo $context->param('title');
 303     * @endcode
 304     *
 305     * @param string $parameter ??????
 306     */
 307    function __unset($parameter)
 308    {
 309        unset($this->_params[$parameter]);
 310    }
 311
 312    /**
 313     * ?????????????? ArrayAccess ??
 314     *
 315     * @code php
 316     * echo isset($context['title']);
 317     * @endcode
 318     *
 319     * @param string $parameter ??????
 320     *
 321     * @return boolean ??????
 322     */
 323    function offsetExists($parameter)
 324    {
 325        if (isset($_GET[$parameter]))
 326            return true;
 327        elseif (isset($_POST[$parameter]))
 328            return true;
 329        else
 330            return isset($this->_params[$parameter]);
 331    }
 332
 333    /**
 334     * ????????? ArrayAccess ??
 335     *
 336     * ?????? __set() ?????
 337     *
 338     * @code php
 339     * $context['title'] = $title;
 340     * echo $context->param('title');
 341     * @endcode
 342     *
 343     * @param string $parameter ??????
 344     * @param mixed $value ???
 345     */
 346    function offsetSet($parameter, $value)
 347    {
 348        $this->changeParam($parameter, $value);
 349    }
 350
 351    /**
 352     * ????????? ArrayAccess ??
 353     *
 354     * @code php
 355     * $title = $context['title'];
 356     * @endcode
 357     *
 358     * @param string $parameter ????????
 359     *
 360     * @return mixed ???
 361     */
 362    function offsetGet($parameter)
 363    {
 364        return $this->query($parameter);
 365    }
 366
 367    /**
 368     * ????????? ArrayAccess ??
 369     *
 370     * ? __unset() ???QContext::offsetUnset() ??? QContext ????????
 371     *
 372     * @code php
 373     * unset($context['title']);
 374     * @endcode
 375     *
 376     * @param string $parameter ????????
 377     */
 378    function offsetUnset($parameter)
 379    {
 380        unset($this->_params[$parameter]);
 381    }
 382
 383    /**
 384     * ???????????
 385     *
 386     * QContext::get() ????????? $context->parameter ??????????
 387     * ?????????????? $default ?????????
 388     *
 389     * @code php
 390     * $title = $context->query('title', 'default title');
 391     * @endcode
 392     *
 393     * ?????????? $_GET?$_POST ? QContext ???????
 394     *
 395     * @param string $parameter ????????
 396     * @param mixed $default ?????????????
 397     *
 398     * @return mixed ???
 399     */
 400    function query($parameter, $default = null)
 401    {
 402        if (isset($_GET[$parameter]))
 403            return $_GET[$parameter];
 404        elseif (isset($_POST[$parameter]))
 405            return $_POST[$parameter];
 406        elseif (isset($this->_params[$parameter]))
 407            return $this->_params[$parameter];
 408        else
 409            return $default;
 410    }
 411
 412    /**
 413     * ?? GET ??
 414     *
 415     * ? $_GET ?????????????????? $default ???????
 416     *
 417     * @code php
 418     * $title = $context->get('title', 'default title');
 419     * @endcode
 420     *
 421     * ?? $parameter ??? null?????? $_GET ????
 422     *
 423     * @param string $parameter ???????
 424     * @param mixed $default ?????????????
 425     *
 426     * @return mixed ???
 427     */
 428    function get($parameter = null, $default = null)
 429    {
 430        if (is_null($parameter))
 431            return $_GET;
 432        return isset($_GET[$parameter]) ? $_GET[$parameter] : $default;
 433    }
 434
 435    /**
 436     * ?? POST ??
 437     *
 438     * ? $_POST ?????????????????? $default ???????
 439     *
 440     * @code php
 441     * $body = $context->post('body', 'default body');
 442     * @endcode
 443     *
 444     * ?? $parameter ??? null?????? $_POST ????
 445     *
 446     * @param string $parameter ???????
 447     * @param mixed $default ?????????????
 448     *
 449     * @return mixed ???
 450     */
 451    function post($parameter = null, $default = null)
 452    {
 453        if (is_null($parameter))
 454            return $_POST;
 455        return isset($_POST[$parameter]) ? $_POST[$parameter] : $default;
 456    }
 457
 458    /**
 459     * ?? Cookie ??
 460     *
 461     * ? $_COOKIE ?????????????????? $default ???????
 462     *
 463     * @code php
 464     * $auto_login = $context->cookie('auto_login');
 465     * @endcode
 466     *
 467     * ?? $parameter ??? null?????? $_COOKIE ????
 468     *
 469     * @param string $parameter ???????
 470     * @param mixed $default ?????????????
 471     *
 472     * @return mixed ???
 473     */
 474    function cookie($parameter = null, $default = null)
 475    {
 476        if (is_null($parameter))
 477            return $_COOKIE;
 478        return isset($_COOKIE[$parameter]) ? $_COOKIE[$parameter] : $default;
 479    }
 480
 481    /**
 482     * ? $_SERVER ???????????
 483     *
 484     * ?????????? $default ???????
 485     *
 486     * @code php
 487     * $request_time = $context->server('REQUEST_TIME');
 488     * @endcode
 489     *
 490     * ?? $parameter ??? null?????? $_SERVER ????
 491     *
 492     * @param string $parameter ???????
 493     * @param mixed $default ?????????????
 494     *
 495     * @return mixed ???
 496     */
 497    function server($parameter = null, $default = null)
 498    {
 499        if (is_null($parameter))
 500            return $_SERVER;
 501        return isset($_SERVER[$parameter]) ? $_SERVER[$parameter] : $default;
 502    }
 503
 504    /**
 505     * ? $_ENV ???????????
 506     *
 507     * ?????????? $default ???????
 508     *
 509     * @code php
 510     * $os_type = $context->env('OS', 'non-win');
 511     * @endcode
 512     *
 513     * ?? $parameter ??? null?????? $_ENV ????
 514     *
 515     * @param string $parameter ???????
 516     * @param mixed $default ?????????????
 517     *
 518     * @return mixed ???
 519     */
 520    function env($parameter = null, $default = null)
 521    {
 522        if (is_null($parameter))
 523            return $_ENV;
 524        return isset($_ENV[$parameter]) ? $_ENV[$parameter] : $default;
 525    }
 526
 527    /**
 528     * ?? QContext ???????
 529     *
 530     * @code php
 531     * $context->changeParam('arg', $value);
 532     * @endcode
 533     *
 534     * @param string $parameter ???????
 535     * @param mixed $value ???
 536     *
 537     * @return QContext ?? QContext ???????????
 538     */
 539    function changeParam($parameter, $value)
 540    {
 541        $this->_params[$parameter] = $value;
 542    }
 543
 544    /**
 545     * ?? QContext ???????
 546     *
 547     * ?????????? $default ???????
 548     *
 549     * @code php
 550     * $value = $context->param('arg', 'default value');
 551     * @endcode
 552     *
 553     * ?? $parameter ??? null??????????????
 554     *
 555     * @param string $parameter ???????
 556     * @param mixed $default ?????????????
 557     *
 558     * @return mixed ???
 559     */
 560    function param($parameter, $default = null)
 561    {
 562        if (is_null($parameter))
 563            return $this->_params;
 564        return isset($this->_params[$parameter]) ? $this->_params[$parameter] : $default;
 565    }
 566
 567    /**
 568     * ?????????
 569     *
 570     */
 571    function params()
 572    {
 573        return $this->_params;
 574    }
 575
 576    /**
 577     * ???????????
 578     *
 579     * ??????????????????? HTTP?
 580     *
 581     * @code php
 582     * $protocol = $context->protocol();
 583     * echo $protocol;
 584     * @endcode
 585     *
 586     * @return string ?????????
 587     */
 588    function protocol()
 589    {
 590        static $protocol;
 591
 592        if (is_null($protocol))
 593        {
 594            list ($protocol) = explode('/', $_SERVER['SERVER_PROTOCOL']);
 595        }
 596        return strtolower($protocol);
 597    }
 598
 599    /**
 600     * ?? REQUEST_URI
 601     *
 602     * ???????? $_SERVER ???????? QContext::requestUri() ??????
 603     * ????? QContext::baseUri() ? QContext::baseDir() ??????
 604     *
 605     * @param string $request_uri ?? REQUEST_URI ?
 606     *
 607     * @return QContext ?? QContext ???????????
 608     */
 609    function changeRequestUri($request_uri)
 610    {
 611        self::$_request_uri = $request_uri;
 612        self::$_base_uri = self::$_base_dir = null;
 613        return $this;
 614    }
 615
 616    /**
 617     * ??????? URL
 618     *
 619     * ?????
 620     *
 621     * <ul>
 622     *   <li>?? http://www.example.com/index.php?controller=posts&action=create</li>
 623     *   <li>?? /index.php?controller=posts&action=create</li>
 624     * </ul>
 625     * <ul>
 626     *   <li>?? http://www.example.com/news/index.php?controller=posts&action=create</li>
 627     *   <li>?? /news/index.php?controller=posts&action=create</li>
 628     * </ul>
 629     * <ul>
 630     *   <li>?? http://www.example.com/index.php/posts/create</li>
 631     *   <li>?? /index.php/posts/create</li>
 632     * </ul>
 633     * <ul>
 634     *   <li>?? http://www.example.com/news/show/id/1</li>
 635     *   <li>?? /news/show/id/1</li>
 636     * </ul>
 637     *
 638     * ????? Zend Framework ???
 639     *
 640     * @return string ????? URL
 641     */
 642    function requestUri()
 643    {
 644        if (self::$_request_uri) return self::$_request_uri;
 645
 646        if (isset($_SERVER['HTTP_X_REWRITE_URL']))
 647        {
 648            $uri = $_SERVER['HTTP_X_REWRITE_URL'];
 649        }
 650        elseif (isset($_SERVER['REQUEST_URI']))
 651        {
 652            $uri = $_SERVER['REQUEST_URI'];
 653        }
 654        elseif (isset($_SERVER['ORIG_PATH_INFO']))
 655        {
 656            $uri = $_SERVER['ORIG_PATH_INFO'];
 657            if (! empty($_SERVER['QUERY_STRING']))
 658            {
 659                $uri .= '?' . $_SERVER['QUERY_STRING'];
 660            }
 661        }
 662        else
 663        {
 664            $uri = '';
 665        }
 666
 667        self::$_request_uri = $uri;
 668        return $uri;
 669    }
 670
 671    /**
 672     * ???????????? URI?????????
 673     *
 674     * ?????
 675     *
 676     * <ul>
 677     *   <li>?? http://www.example.com/index.php?controller=posts&action=create</li>
 678     *   <li>?? /index.php</li>
 679     * </ul>
 680     * <ul>
 681     *   <li>?? http://www.example.com/news/index.php?controller=posts&action=create</li>
 682     *   <li>?? /news/index.php</li>
 683     * </ul>
 684     * <ul>
 685     *   <li>?? http://www.example.com/index.php/posts/create</li>
 686     *   <li>?? /index.php</li>
 687     * </ul>
 688     * <ul>
 689     *   <li>?? http://www.example.com/news/show/id/1</li>
 690     *   <li>?? /news/show/id/1</li>
 691     *   <li>????? URL ????? index.php ?????</li>
 692     * </ul>
 693     *
 694     * ????? Zend Framework ???
 695     *
 696     * @return string ?? URL ???????????
 697     */
 698    function baseUri()
 699    {
 700        if (self::$_base_uri) return self::$_base_uri;
 701
 702        $filename = basename($_SERVER['SCRIPT_FILENAME']);
 703
 704        if (basename($_SERVER['SCRIPT_NAME']) === $filename)
 705        {
 706            $url = $_SERVER['SCRIPT_NAME'];
 707        }
 708        elseif (basename($_SERVER['PHP_SELF']) === $filename)
 709        {
 710            $url = $_SERVER['PHP_SELF'];
 711        }
 712        elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename)
 713        {
 714            $url = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility
 715        }
 716        else
 717        {
 718            // Backtrack up the script_filename to find the portion matching
 719            // php_self
 720            $path = $_SERVER['PHP_SELF'];
 721            $segs = explode('/', trim($_SERVER['SCRIPT_FILENAME'], '/'));
 722            $segs = array_reverse($segs);
 723            $index = 0;
 724            $last = count($segs);
 725            $url = '';
 726            do
 727            {
 728                $seg = $segs[$index];
 729                $url = '/' . $seg . $url;
 730                ++ $index;
 731            } while (($last > $index) && (false !== ($pos = strpos($path, $url))) && (0 != $pos));
 732        }
 733
 734        // Does the baseUrl have anything in common with the request_uri?
 735        $request_uri = $this->requestUri();
 736
 737        if (0 === strpos($request_uri, $url))
 738        {
 739            // full $url matches
 740            self::$_base_uri = $url;
 741            return self::$_base_uri;
 742        }
 743
 744        if (0 === strpos($request_uri, dirname($url)))
 745        {
 746            // directory portion of $url matches
 747            self::$_base_uri = rtrim(dirname($url), '/') . '/';
 748            return self::$_base_uri;
 749        }
 750
 751        if (! strpos($request_uri, basename($url)))
 752        {
 753            // no match whatsoever; set it blank
 754            return '';
 755        }
 756
 757        // If using mod_rewrite or ISAPI_Rewrite strip the script filename
 758        // out of baseUrl. $pos !== 0 makes sure it is not matching a value
 759        // from PATH_INFO or QUERY_STRING
 760        if ((strlen($request_uri) >= strlen($url))
 761            && ((false !== ($pos = strpos($request_uri, $url)))
 762            && ($pos !== 0)))
 763        {
 764            $url = substr($request_uri, 0, $pos + strlen($url));
 765        }
 766
 767        self::$_base_uri = rtrim($url, '/') . '/';
 768        return self::$_base_uri;
 769    }
 770
 771    /**
 772     * ???? URL ???????????????
 773     *
 774     * ?????
 775     *
 776     * <ul>
 777     *   <li>?? http://www.example.com/index.php?controller=posts&action=create</li>
 778     *   <li>?? /</li>
 779     * </ul>
 780     * <ul>
 781     *   <li>?? http://www.example.com/news/index.php?controller=posts&action=create</li>
 782     *   <li>?? /news/</li>
 783     * </ul>
 784     * <ul>
 785     *   <li>?? http://www.example.com/index.php/posts/create</li>
 786     *   <li>?? /</li>
 787     * </ul>
 788     * <ul>
 789     *   <li>?? http://www.example.com/news/show/id/1</li>
 790     *   <li>?? /</li>
 791     * </ul>
 792     *
 793     * @return string ?? URL ??????
 794     */
 795    function baseDir()
 796    {
 797        if (self::$_base_dir) return self::$_base_dir;
 798
 799        $base_uri = $this->baseUri();
 800        if (substr($base_uri, - 1, 1) == '/')
 801        {
 802            $base_dir = $base_uri;
 803        }
 804        else
 805        {
 806            $base_dir = dirname($base_uri);
 807        }
 808
 809        self::$_base_dir = rtrim($base_dir, '/\\') . '/';
 810        return self::$_base_dir;
 811    }
 812
 813    /**
 814     * ??????????????
 815     *
 816     * ??????? 80 ???????????????????????????
 817     *
 818     * @return string ????????????
 819     */
 820    function serverPort()
 821    {
 822        static $server_port = null;
 823
 824        if ($server_port) return $server_port;
 825
 826        if (isset($_SERVER['SERVER_PORT']))
 827        {
 828            $server_port = intval($_SERVER['SERVER_PORT']);
 829        }
 830        else
 831        {
 832            $server_port = 80;
 833        }
 834
 835        if (isset($_SERVER['HTTP_HOST']))
 836        {
 837            $arr = explode(':', $_SERVER['HTTP_HOST']);
 838            $count = count($arr);
 839            if ($count > 1)
 840            {
 841                $port = intval($arr[$count - 1]);
 842                if ($port != $server_port)
 843                {
 844                    $server_port = $port;
 845                }
 846            }
 847        }
 848
 849        return $server_port;
 850    }
 851
 852    /**
 853     * ????????????
 854     *
 855     * @return string ??????????
 856     */
 857    function scriptName()
 858    {
 859        return basename($_SERVER['SCRIPT_FILENAME']);
 860    }
 861
 862    /**
 863     * ?? PATHINFO ??
 864     *
 865     * <ul>
 866     *   <li>?? http://www.example.com/index.php?controller=posts&action=create</li>
 867     *   <li>?? /</li>
 868     * </ul>
 869     * <ul>
 870     *   <li>?? http://www.example.com/news/index.php?controller=posts&action=create</li>
 871     *   <li>?? /</li>
 872     * </ul>
 873     * <ul>
 874     *   <li>?? http://www.example.com/index.php/posts/create</li>
 875     *   <li>?? /</li>
 876     * </ul>
 877     * <ul>
 878     *   <li>?? http://www.example.com/news/show/id/1</li>
 879     *   <li>?? /news/show/id/1</li>
 880     *   <li>????? URL ????? index.php ?????</li>
 881     * </ul>
 882     *
 883     * ????? Zend Framework ???
 884     *
 885     * @return string
 886     */
 887    function pathinfo()
 888    {
 889        if (!empty($_SERVER['PATH_INFO'])) return $_SERVER['PATH_INFO'];
 890
 891        $base_url = $this->baseUri();
 892
 893        if (null === ($request_uri = $this->requestUri())) return '';
 894
 895        // Remove the query string from REQUEST_URI
 896        if (($pos = strpos($request_uri, '?')))
 897        {
 898            $request_uri = substr($request_uri, 0, $pos);
 899        }
 900
 901        if ((null !== $base_url) && (false === ($pathinfo = substr($request_uri, strlen($base_url)))))
 902        {
 903            // If substr() returns false then PATH_INFO is set to an empty string
 904            $pathinfo = '';
 905        }
 906        elseif (null === $base_url)
 907        {
 908            $pathinfo = $request_uri;
 909        }
 910
 911        return $pathinfo;
 912    }
 913
 914    /**
 915     * ?????????
 916     *
 917     * @return string
 918     */
 919    function requestMethod()
 920    {
 921        return $_SERVER['REQUEST_METHOD'];
 922    }
 923
 924    /**
 925     * ??? GET ??
 926     *
 927     * @return boolean
 928     */
 929    function isGET()
 930    {
 931        return $this->requestMethod() == 'GET';
 932    }
 933
 934    /**
 935     * ??? POST ??
 936     *
 937     * @return boolean
 938     */
 939    function isPOST()
 940    {
 941        return $this->requestMethod() == 'POST';
 942    }
 943
 944    /**
 945     * ??? PUT ??
 946     *
 947     * @return boolean
 948     */
 949    function isPUT()
 950    {
 951        return $this->requestMethod() == 'PUT';
 952    }
 953
 954    /**
 955     * ??? DELETE ??
 956     *
 957     * @return boolean
 958     */
 959    function isDELETE()
 960    {
 961        return $this->requestMethod() == 'DELETE';
 962    }
 963
 964    /**
 965     * ??? HEAD ??
 966     *
 967     * @return boolean
 968     */
 969    function isHEAD()
 970    {
 971        return $this->requestMethod() == 'HEAD';
 972    }
 973
 974    /**
 975     * ??? OPTIONS ??
 976     *
 977     * @return boolean
 978     */
 979    function isOPTIONS()
 980    {
 981        return $this->requestMethod() == 'OPTIONS';
 982    }
 983
 984    /**
 985     * ?? HTTP ??????? XMLHttp ???
 986     *
 987     * @return boolean
 988     */
 989    function isAJAX()
 990    {
 991        return strtolower($this->header('X_REQUESTED_WITH')) == 'xmlhttprequest';
 992    }
 993
 994    /**
 995     * ?? HTTP ??????? Flash ???
 996     *
 997     * @return boolean
 998     */
 999    function isFlash()
1000    {
1001        return strtolower($this->header('USER_AGENT')) == 'shockwave flash';
1002    }
1003
1004    /**
1005     * ?????????
1006     *
1007     * @return string
1008     */
1009    function requestRawBody()
1010    {
1011        $body = file_get_contents('php://input');
1012        return (strlen(trim($body)) > 0) ? $body : false;
1013    }
1014
1015    /**
1016     * ?? HTTP ????????????????????? false
1017     *
1018     * @param string $header ?????????
1019     *
1020     * @return string ???
1021     */
1022    function header($header)
1023    {
1024        $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $header));
1025        if (!empty($_SERVER[$temp])) return $_SERVER[$temp];
1026
1027        if (function_exists('apache_request_headers'))
1028        {
1029            $headers = apache_request_headers();
1030            if (!empty($headers[$header])) return $headers[$header];
1031        }
1032
1033        return false;
1034    }
1035
1036    /**
1037     * ????????? URL
1038     *
1039     * @return string ??????? URL
1040     */
1041    function referer()
1042    {
1043        return $this->header('REFERER');
1044    }
1045
1046    /**
1047     * ?????????????
1048     *
1049     * ???????????? null?
1050     *
1051     * @return QRouter ???????????
1052     */
1053    function router()
1054    {
1055        return $this->_router;
1056    }
1057
1058    /**
1059     * ?? url
1060     *
1061     * ???
1062     *
1063     * @code php
1064     * url(UDI, [??????], [???])
1065     * @endcode
1066     *
1067     * UDI ??????????Uniform Destination Identifier?????
1068     * UDI ????????????????????????????
1069     *
1070     * @code php
1071     * namespace::controller/action@module
1072     * @endcode
1073     *
1074     * UDI ????????????????
1075     * ??????????????????????????????index????
1076     * ??????????????????????????
1077     *
1078     * UDI ????????
1079     *
1080     * @code php
1081     * 'controller'
1082     * 'controller/action'
1083     * '/action'
1084     * 'controller@module'
1085     * 'controller/action@module'
1086     * 'namespace::controller'
1087     * 'namespace::controller/action'
1088     * 'namespace::controller@module'
1089     * 'namespace::controller/action@module'
1090     * '@module'
1091     * 'namespace::@module'
1092     * @endcode
1093     *
1094     * ???
1095     * @code php
1096     * url('admin::posts/edit', array('id' => $post->id()));
1097     * @endcode
1098     *
1099     * $params ??????????????“/”?????????
1100     *
1101     * @code php
1102     * url('posts/index', 'page/3');
1103     * url('users/show', 'id/5/profile/yes');
1104     * @endcode
1105     *
1106     * ??? PATHINFO ? URL ???????????????????? QeePHP
1107     * ???????????? URL????????????? URL ????
1108     * ???????????????????? URL ????
1109     *
1110     * $opts ?????????? URL????????
1111     *
1112     * -  base_uri: ?? URL ???????????????????????????
1113     * -  script: ?? URL ?????????
1114     * -  mode: ?? URL ???????? standard?pathinfo ? rewrite
1115     *
1116     * @param string $udi UDI ???
1117     * @param array|string $params ??????
1118     * @param string $route_name ???
1119     * @param array $opts ?????? URL ???
1120     *
1121     * @return string ??? URL ??
1122     */
1123    function url($udi, $params = null, $route_name = null, array $opts = null)
1124    {
1125        static $base_uri;
1126
1127        if (is_null($base_uri))
1128        {
1129            $base_uri = '/' . trim($this->baseDir(), '/');
1130            if ($base_uri != '/')
1131            {
1132                $base_uri .= '/';
1133            }
1134        }
1135        $udi = $this->normalizeUDI($udi);
1136
1137        if (!is_array($params))
1138        {
1139            $arr = Q::normalize($params, '/');
1140            $params = array();
1141            while ($key = array_shift($arr))
1142            {
1143                $value = array_shift($arr);
1144                $params[$key] = $value;
1145            }
1146        }
1147
1148        // ?? $opts
1149        if (is_array($opts))
1150        {
1151            $mode   = !empty($opts['mode']) ? $opts['mode'] : self::$_url_mode;
1152            $script = !empty($opts['script'])
1153                    ? $opts['script']
1154                    : $this->scriptName();
1155            $url    = !empty($opts['base_uri'])
1156                    ? rtrim($opts['base_uri'], '/') . '/'
1157                    : $base_uri;
1158        }
1159        else
1160        {
1161            $mode   = self::$_url_mode;
1162            $url    = $base_uri;
1163            $script = $this->scriptName();
1164        }
1165        if (!is_null($this->_router) && $mode != self::URL_MODE_STANDARD)
1166        {
1167            // ?????? URL
1168            $params = array_merge($params, $udi);
1169            $path = $this->_router->url($params, $route_name);
1170            if (self::$_url_mode == self::URL_MODE_PATHINFO && $path != '/')
1171            {
1172                $url .= $this->scriptName();
1173            }
1174            else
1175            {
1176                $url = rtrim($url, '/');
1177            }
1178            $url .= $path;
1179        }
1180        else
1181        {
1182            foreach (self::$_udi_defaults as $key => $value)
1183            {
1184                if ($udi[$key] == $value) unset($udi[$key]);
1185                unset($params[$key]);
1186            }
1187
1188            $params = array_filter(array_merge($udi, $params));
1189            $url .= $script;
1190            if (!empty($params))
1191            {
1192                $url .= '?' . http_build_query($params, '', '&');
1193            }
1194        }
1195        return $url;
1196    }
1197
1198    /**
1199     * ?? UDI ????????
1200     *
1201     * @param array $udi ???? UDI
1202     *
1203     * @return string
1204     */
1205    function UDIString(array $udi)
1206    {
1207        return "{$udi[self::UDI_NAMESPACE]}::{$udi[self::UDI_CONTROLLER]}/{$udi[self::UDI_ACTION]}@{$udi[self::UDI_MODULE]}";
1208    }
1209
1210    /**
1211     * ???????? UDI ??
1212     *
1213     * @code php
1214     * $udi = array(
1215     *     QContext::UDI_CONTROLLER => '',
1216     *     QContext::UDI_ACTION     => '',
1217     *     QContext::UDI_NAMESPACE  => '',
1218     *     QContext::UDI_MODULE     => '',
1219     * );
1220     *
1221     * // ??
1222     * // array(
1223     * //     controller: default
1224     * //     action:     index
1225     * //     namespace:  default
1226     * //     module:     default
1227     * // )
1228     * dump($context->normalizeUDI($udi));
1229     *
1230     * $udi = 'admin::posts/edit';
1231     * // ??
1232     * // array(
1233     * //     controller: posts
1234     * //     action:     edit
1235     * //     namespace:  admin
1236     * //     module:     default
1237     * // )
1238     * dump($context->normalizeUDI($udi));
1239     * @endcode
1240     *
1241     * ??????????? UDI??? $return_array ??? false?
1242     *
1243     * @param string|array $udi ???? UDI
1244     * @param boolean $return_array ????????? UDI
1245     *
1246     * @return array ???? UDI
1247     */
1248    function normalizeUDI($udi, $return_array = true)
1249    {
1250        if (!is_array($udi))
1251        {
1252            // ???? ".", "/" UDI??
1253            // url('.') ??????
1254            // url('/') ???????+index
1255            if($udi === '.')
1256            {
1257                $namespace = $this->namespace;
1258                $module_name = $this->module_name;
1259                $controller = $this->controller;
1260                $action = $this->action;
1261            }
1262            elseif($udi === '/')
1263            {
1264                $namespace = $this->namespace;
1265                $module_name = $this->module_name;
1266                $controller = $this->controller;
1267                $action = self::$_udi_defaults[self::UDI_ACTION];
1268            }
1269            else
1270            {
1271                if (strpos($udi, '::') !== false)
1272                {
1273                    $arr = explode('::', $udi);
1274                    $namespace = array_shift($arr);
1275                    $udi = array_shift($arr);
1276                }
1277                else
1278                {
1279                    $namespace = $this->namespace;
1280                }
1281
1282                if (strpos($udi, '@') !== false)
1283                {
1284                    $arr = explode('@', $udi);
1285                    $module_name = array_pop($arr);
1286                    $udi = array_pop($arr);
1287                }
1288                else
1289                {
1290                    $module_name = $this->module_name;
1291                }
1292
1293                $arr = explode('/', $udi);
1294                $controller = array_shift($arr);
1295                $action = array_shift($arr);
1296            }
1297
1298            $udi = array(
1299                self::UDI_MODULE     => $module_name,
1300                self::UDI_NAMESPACE  => $namespace,
1301                self::UDI_CONTROLLER => $controller,
1302                self::UDI_ACTION     => $action,
1303            );
1304        }
1305
1306        if (empty($udi[self::UDI_MODULE]))
1307        {
1308            $udi[self::UDI_MODULE] = $this->module_name;
1309        }
1310        if (empty($udi[self::UDI_NAMESPACE]))
1311        {
1312            $udi[self::UDI_NAMESPACE] = $this->namespace;
1313        }
1314        if (empty($udi[self::UDI_CONTROLLER]))
1315        {
1316            $udi[self::UDI_CONTROLLER] = $this->controller_name;
1317        }
1318        if (empty($udi[self::UDI_ACTION]) && $udi[self::UDI_ACTION] !== '0')
1319        {
1320            $udi[self::UDI_ACTION] = self::UDI_DEFAULT_ACTION;
1321        }
1322        foreach (self::$_udi_defaults as $key => $value)
1323        {
1324            if (empty($udi[$key]) && $udi[$key] !== '0')
1325            {
1326                $udi[$key] = $value;
1327            }
1328            else
1329            {
1330                $udi[$key] = preg_replace('/[^a-z0-9]+/', '', strtolower($udi[$key]));
1331            }
1332        }
1333
1334        if (!$return_array)
1335        {
1336            return "{$udi[self::UDI_NAMESPACE]}::{$udi[self::UDI_CONTROLLER]}/{$udi[self::UDI_ACTION]}@{$udi[self::UDI_MODULE]}";
1337        }
1338        else
1339        {
1340            return $udi;
1341        }
1342    }
1343
1344    /**
1345     * ????????? UDI
1346     *
1347     * ?????????????????????????????????? UDI?
1348     *
1349     * @code php
1350     * dump($context->requestUDI());
1351     * @endcode
1352     *
1353     * @param boolean $return_array ????????? UDI
1354     *
1355     * @return string|array ??????? UDI
1356     */
1357    function requestUDI($return_array = true)
1358    {
1359        return $this->normalizeUDI("/{$this->action_name}", $return_array);
1360    }
1361
1362    /**
1363     * ? QContext ???????????? UDI ????
1364     *
1365     * @code php
1366     * $context->changeRequestUDI('posts/edit');
1367     * // ??? posts
1368     * echo $context->controller_name;
1369     * @endcode
1370     *
1371     * @param array|string $udi ???? UDI
1372     *
1373     * @return QContext ?? QContext ???????????
1374     */
1375    function changeRequestUDI($udi)
1376    {
1377        $udi = $this->normalizeUDI($udi);
1378        
1379        $this->controller_name = $udi[self::UDI_CONTROLLER];
1380        $this->action_name     = $udi[self::UDI_ACTION];
1381        $this->module_name     = $udi[self::UDI_MODULE];
1382        $this->namespace       = $udi[self::UDI_NAMESPACE];
1383
1384        if ($this->module_name == self::UDI_DEFAULT_MODULE)
1385        {
1386            $this->module_name = null;
1387        }
1388        if ($this->namespace   == self::UDI_DEFAULT_NAMESPACE)
1389        {
1390            $this->namespace = null;
1391        }
1392        return $this;
1393    }
1394}
1395