ApplicationUrl.class.php

Go to the documentation of this file.
00001 <?php
00002 /***************************************************************************
00003  *   Copyright (C) 2007-2009 by Ivan Y. Khvostishkov                       *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU Lesser General Public License as        *
00007  *   published by the Free Software Foundation; either version 3 of the    *
00008  *   License, or (at your option) any later version.                       *
00009  *                                                                         *
00010  ***************************************************************************/
00011 
00017     class ApplicationUrl
00018     {
00019         protected $base             = null;
00020         
00021         protected $applicationScope = array();
00022         protected $userScope            = array();
00023         protected $navigationScope  = array();
00024         
00025         protected $argSeparator     = null;
00026         
00027         protected $navigationSchema = null;
00028         
00029         protected $absolute         = false;
00030         
00034         public static function create()
00035         {
00036             return new self;
00037         }
00038         
00042         public function setBase(HttpUrl $base)
00043         {
00044             $this->base = $base;
00045             
00046             return $this;
00047         }
00048         
00052         public function getBase()
00053         {
00054             return $this->base;
00055         }
00056         
00060         public function setAbsolute($absolute)
00061         {
00062             $this->absolute = $absolute;
00063             
00064             return $this;
00065         }
00066         
00067         public function isAbsolute()
00068         {
00069             return $this->absolute;
00070         }
00071         
00075         public function setNavigationSchema(ScopeNavigationSchema $schema)
00076         {
00077             $this->navigationSchema = $schema;
00078             
00079             return $this;
00080         }
00081         
00085         public function getNavigationSchema()
00086         {
00087             return $this->navigationSchema;
00088         }
00089         
00093         public function addApplicationScope($scope)
00094         {
00095             Assert::isArray($scope);
00096             
00097             $this->applicationScope = ArrayUtils::mergeRecursiveUnique(
00098                 $this->applicationScope, $scope
00099             );
00100             
00101             return $this;
00102         }
00103         
00107         public function addUserScope($userScope)
00108         {
00109             Assert::isArray($userScope);
00110             
00111             $this->userScope = ArrayUtils::mergeRecursiveUnique(
00112                 $this->userScope, $userScope
00113             );
00114             
00115             return $this;
00116         }
00117 
00121         public function dropFromUserScope($key)
00122         {
00123             if (isset($this->userScope[$key]))
00124                 $this->userScope[$key] = null;
00125 
00126             return $this;
00127         }
00128         
00129         public function getUserScope()
00130         {
00131             return $this->userScope;
00132         }
00133         
00137         public function setPath($path)
00138         {
00139             if (!$this->navigationSchema)
00140                 throw new WrongStateException(
00141                     'charly says always set navigation schema'
00142                     .' before you go off somewhere'
00143                 );
00144             
00145             $scope = $this->navigationSchema->getScope($path);
00146             
00147             if ($scope === null)
00148                 throw new WrongArgumentException(
00149                     '404: not found'
00150                 );
00151             
00152             $this->navigationScope = $scope;
00153             
00154             return $this;
00155         }
00156         
00160         public function setPathByRequestUri($requestUri, $normalize = true)
00161         {
00162             if (!$this->base)
00163                 throw new WrongStateException(
00164                     'base url must be set first'
00165                 );
00166             
00167             $currentUrl = GenericUri::create()->
00168                 parse($requestUri);
00169             
00170             if (!$currentUrl->isValid())
00171                 throw new WrongArgumentException(
00172                     'wtf? request uri is invalid'
00173                 );
00174             
00175             if ($normalize)
00176                 $currentUrl->normalize();
00177             
00178             $path = $currentUrl->getPath();
00179             
00180             // paranoia
00181             if (!$path || ($path[0] !== '/'))
00182                 $path = '/'.$path;
00183             
00184             if (strpos($path, $this->base->getPath()) !== 0)
00185                 throw new WrongArgumentException(
00186                     'left parts of path and base url does not match: '
00187                     ."$path vs. ".$this->base->getPath()
00188                 );
00189             
00190             $actualPath = substr($path, strlen($this->base->getPath()));
00191             
00192             return $this->setPath($actualPath);
00193         }
00194         
00195         public function getNavigationScope()
00196         {
00197             return $this->navigationScope;
00198         }
00199         
00200         public function getArgSeparator()
00201         {
00202             if (!$this->argSeparator)
00203                 return ini_get('arg_separator.output');
00204             else
00205                 return $this->argSeparator;
00206         }
00207         
00211         public function setArgSeparator($argSeparator)
00212         {
00213             $this->argSeparator = $argSeparator;
00214             
00215             return $this;
00216         }
00217         
00218         public function currentHref(
00219             $additionalScope = array(),
00220             $absolute = null
00221         )
00222         {
00223             return $this->scopeHref(
00224                 ArrayUtils::mergeRecursiveUnique(
00225                     $this->userScope, $additionalScope
00226                 ),
00227                 $absolute
00228             );
00229         }
00230         
00231         public function scopeHref($scope, $absolute = null)
00232         {
00233             Assert::isArray($scope);
00234             
00235             // href scope may override navigation scope
00236             $actualScope = ArrayUtils::mergeRecursiveUnique(
00237                 $this->navigationScope, $scope
00238             );
00239             
00240             return $this->cleanHref($actualScope, $absolute);
00241         }
00242         
00243         public function cleanHref($scope, $absolute = null)
00244         {
00245             Assert::isArray($scope);
00246             
00247             $path = $this->navigationSchema
00248                 ? $this->navigationSchema->extractPath($scope)
00249                 : null;
00250             
00251             return $this->href($path.'?'.$this->buildQuery($scope), $absolute);
00252         }
00253         
00254         public function baseHref($absolute = null)
00255         {
00256             return $this->href(null, $absolute);
00257         }
00258         
00259         public function poorReference($url)
00260         {
00261             Assert::isNotNull($this->base, 'set base url first');
00262             
00263             $parsedUrl = HttpUrl::create()->parse($url);
00264             
00265             return $this->base->transform($parsedUrl);
00266         }
00267         
00268         public function href($url, $absolute = null)
00269         {
00270             if ($absolute === null)
00271                 $absolute = $this->absolute;
00272             
00273             $result = $this->poorReference($url);
00274             
00275             if ($this->applicationScope)
00276                 $result->appendQuery(
00277                     $this->buildQuery($this->applicationScope),
00278                     $this->getArgSeparator()
00279                 );
00280             
00281             $result->normalize();
00282             
00283             if ($result->getQuery() === '')
00284                 $result->setQuery(null);
00285             
00286             if ($absolute)
00287                 return $result->toString();
00288             else
00289                 return $result->toStringFromRoot();
00290         }
00291         
00292         public function absoluteHref($url)
00293         {
00294             return $this->href($url, true);
00295         }
00296         
00297         public function getUserQueryVars()
00298         {
00299             return $this->getQueryVars($this->userScope);
00300         }
00301         
00302         public function getApplicationQueryVars()
00303         {
00304             return $this->getQueryVars($this->applicationScope);
00305         }
00306         
00307         protected function getQueryVars($scope)
00308         {
00309             $queryParts = explode(
00310                 $this->getArgSeparator(),
00311                 $this->buildQuery($scope)
00312             );
00313             
00314             $result = array();
00315             
00316             foreach ($queryParts as $queryPart) {
00317                 if (!$queryPart)
00318                     continue;
00319                 
00320                 list($key, $value) = explode('=', $queryPart, 2);
00321                 
00322                 $result[$key] = $value;
00323             }
00324             
00325             return $result;
00326         }
00327         
00328         protected function buildQuery($scope)
00329         {
00330             return http_build_query(
00331                 $scope, null, $this->getArgSeparator()
00332             );
00333         }
00334     }
00335 ?>