[ Index ]
 

Code source de Symfony 1.0.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/util/ -> sfBrowser.class.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the symfony package.
   5   * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
   6   *
   7   * For the full copyright and license information, please view the LICENSE
   8   * file that was distributed with this source code.
   9   */
  10  
  11  /**
  12   * sfBrowser simulates a fake browser which can surf a symfony application.
  13   *
  14   * @package    symfony
  15   * @subpackage util
  16   * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
  17   * @version    SVN: $Id: sfBrowser.class.php 3334 2007-01-23 15:46:08Z fabien $
  18   */
  19  class sfBrowser
  20  {
  21    protected
  22      $context            = null,
  23      $hostname           = null,
  24      $remote             = null,
  25      $dom                = null,
  26      $stack              = array(),
  27      $stackPosition      = -1,
  28      $cookieJar          = array(),
  29      $fields             = array(),
  30      $vars               = array(),
  31      $defaultServerArray = array(),
  32      $currentException   = null;
  33  
  34    public function initialize($hostname = null, $remote = null, $options = array())
  35    {
  36      unset($_SERVER['argv']);
  37      unset($_SERVER['argc']);
  38  
  39      // setup our fake environment
  40      $this->hostname = $hostname;
  41      $this->remote   = $remote;
  42  
  43      sfConfig::set('sf_path_info_array', 'SERVER');
  44      sfConfig::set('sf_test', true);
  45  
  46      // we set a session id (fake cookie / persistence)
  47      $this->newSession();
  48  
  49      // store default global $_SERVER array
  50      $this->defaultServerArray = $_SERVER;
  51  
  52      // register our shutdown function
  53      register_shutdown_function(array($this, 'shutdown'));
  54    }
  55  
  56    public function setVar($name, $value)
  57    {
  58      $this->vars[$name] = $value;
  59  
  60      return $this;
  61    }
  62  
  63    public function setAuth($login, $password)
  64    {
  65      $this->vars['PHP_AUTH_USER'] = $login;
  66      $this->vars['PHP_AUTH_PW']   = $password;
  67  
  68      return $this;
  69    }
  70  
  71    public function get($uri, $parameters = array())
  72    {
  73      return $this->call($uri, 'get', $parameters);
  74    }
  75  
  76    public function post($uri, $parameters = array())
  77    {
  78      return $this->call($uri, 'post', $parameters);
  79    }
  80  
  81    public function call($uri, $method = 'get', $parameters = array(), $changeStack = true)
  82    {
  83      $uri = $this->fixUri($uri);
  84  
  85      // add uri to the stack
  86      if ($changeStack)
  87      {
  88        $this->stack = array_slice($this->stack, 0, $this->stackPosition + 1);
  89        $this->stack[] = array(
  90          'uri'        => $uri,
  91          'method'     => $method,
  92          'parameters' => $parameters,
  93        );
  94        $this->stackPosition = count($this->stack) - 1;
  95      }
  96  
  97      list($path, $query_string) = false !== ($pos = strpos($uri, '?')) ? array(substr($uri, 0, $pos), substr($uri, $pos + 1)) : array($uri, '');
  98      $query_string = html_entity_decode($query_string);
  99  
 100      // remove anchor
 101      $path = preg_replace('/#.*/', '', $path);
 102  
 103      // removes all fields from previous request
 104      $this->fields = array();
 105  
 106      // prepare the request object
 107      $_SERVER = $this->defaultServerArray;
 108      $_SERVER['HTTP_HOST']       = $this->hostname ? $this->hostname : sfConfig::get('sf_app').'-'.sfConfig::get('sf_environment');
 109      $_SERVER['SERVER_NAME']     = $_SERVER['HTTP_HOST'];
 110      $_SERVER['SERVER_PORT']     = 80;
 111      $_SERVER['HTTP_USER_AGENT'] = 'PHP5/CLI';
 112      $_SERVER['REMOTE_ADDR']     = $this->remote ? $this->remote : '127.0.0.1';
 113      $_SERVER['REQUEST_METHOD']  = strtoupper($method);
 114      $_SERVER['PATH_INFO']       = $path;
 115      $_SERVER['REQUEST_URI']     = '/index.php'.$uri;
 116      $_SERVER['SCRIPT_NAME']     = '/index.php';
 117      $_SERVER['SCRIPT_FILENAME'] = '/index.php';
 118      $_SERVER['QUERY_STRING']    = $query_string;
 119      foreach ($this->vars as $key => $value)
 120      {
 121        $_SERVER[strtoupper($key)] = $value;
 122      }
 123  
 124      // request parameters
 125      $_GET = $_POST = array();
 126      if (strtoupper($method) == 'POST')
 127      {
 128        $_POST = $parameters;
 129      }
 130      if (strtoupper($method) == 'GET')
 131      {
 132        $_GET  = $parameters;
 133      }
 134      parse_str($query_string, $qs);
 135      if (is_array($qs))
 136      {
 137        $_GET = array_merge($qs, $_GET);
 138      }
 139  
 140      // restore cookies
 141      $_COOKIE = array();
 142      foreach ($this->cookieJar as $name => $cookie)
 143      {
 144        $_COOKIE[$name] = $cookie['value'];
 145      }
 146  
 147      // recycle our context object
 148      sfContext::removeInstance();
 149      $this->context = sfContext::getInstance();
 150  
 151      // launch request via controller
 152      $controller = $this->context->getController();
 153      $request    = $this->context->getRequest();
 154      $response   = $this->context->getResponse();
 155  
 156      // we register a fake rendering filter
 157      sfConfig::set('sf_rendering_filter', array('sfFakeRenderingFilter', null));
 158  
 159      $this->currentException = null;
 160  
 161      // dispatch our request
 162      ob_start();
 163      try
 164      {
 165        $controller->dispatch();
 166      }
 167      catch (sfException $e)
 168      {
 169        $this->currentException = $e;
 170  
 171        $e->printStackTrace();
 172      }
 173      catch (Exception $e)
 174      {
 175        $this->currentException = $e;
 176  
 177        $sfException = new sfException();
 178        $sfException->printStackTrace($e);
 179      }
 180      $retval = ob_get_clean();
 181  
 182      if ($this->currentException instanceof sfStopException)
 183      {
 184        $this->currentException = null;
 185      }
 186  
 187      // append retval to the response content
 188      $response->setContent($retval);
 189  
 190      // manually shutdown user to save current session data
 191      $this->context->getUser()->shutdown();
 192      $this->context->getStorage()->shutdown();
 193  
 194      // save cookies
 195      $this->cookieJar = array();
 196      foreach ($response->getCookies() as $name => $cookie)
 197      {
 198        // FIXME: deal with expire, path, secure, ...
 199        $this->cookieJar[$name] = $cookie;
 200      }
 201  
 202      // for HTML/XML content, create a DOM and sfDomCssSelector objects for the response content
 203      if (preg_match('/(x|ht)ml/i', $response->getContentType()))
 204      {
 205        $this->dom = new DomDocument('1.0', sfConfig::get('sf_charset'));
 206        $this->dom->validateOnParse = true;
 207        @$this->dom->loadHTML($response->getContent());
 208        $this->domCssSelector = new sfDomCssSelector($this->dom);
 209      }
 210  
 211      return $this;
 212    }
 213  
 214    public function back()
 215    {
 216      if ($this->stackPosition < 1)
 217      {
 218        throw new sfException('You are already on the first page.');
 219      }
 220  
 221      --$this->stackPosition;
 222      return $this->call($this->stack[$this->stackPosition]['uri'], $this->stack[$this->stackPosition]['method'], $this->stack[$this->stackPosition]['parameters'], false);
 223    }
 224  
 225    public function forward()
 226    {
 227      if ($this->stackPosition > count($this->stack) - 2)
 228      {
 229        throw new sfException('You are already on the last page.');
 230      }
 231  
 232      ++$this->stackPosition;
 233      return $this->call($this->stack[$this->stackPosition]['uri'], $this->stack[$this->stackPosition]['method'], $this->stack[$this->stackPosition]['parameters'], false);
 234    }
 235  
 236    public function reload()
 237    {
 238      if (-1 == $this->stackPosition)
 239      {
 240        throw new sfException('No page to reload.');
 241      }
 242  
 243      return $this->call($this->stack[$this->stackPosition]['uri'], $this->stack[$this->stackPosition]['method'], $this->stack[$this->stackPosition]['parameters'], false);
 244    }
 245  
 246    public function getResponseDomCssSelector()
 247    {
 248      return $this->domCssSelector;
 249    }
 250  
 251    public function getResponseDom()
 252    {
 253      return $this->dom;
 254    }
 255  
 256    public function getContext()
 257    {
 258      return $this->context;
 259    }
 260  
 261    public function getResponse()
 262    {
 263      return $this->context->getResponse();
 264    }
 265  
 266    public function getRequest()
 267    {
 268      return $this->context->getRequest();
 269    }
 270  
 271    public function getCurrentException()
 272    {
 273      return $this->currentException;
 274    }
 275  
 276    public function followRedirect()
 277    {
 278      if (null === $this->getContext()->getResponse()->getHttpHeader('Location'))
 279      {
 280        throw new sfException('The request was not redirected');
 281      }
 282  
 283      return $this->get($this->getContext()->getResponse()->getHttpHeader('Location'));
 284    }
 285  
 286    public function setField($name, $value)
 287    {
 288      // as we don't know yet the form, just store name/value pairs
 289      $this->parseArgumentAsArray($name, $value, $this->fields);
 290  
 291      return $this;
 292    }
 293  
 294    // link or button
 295    public function click($name, $arguments = array())
 296    {
 297      if (!$this->dom)
 298      {
 299        throw new sfException('Cannot click because there is no current page in the browser');
 300      }
 301  
 302      $xpath = new DomXpath($this->dom);
 303      $dom   = $this->dom;
 304  
 305      // text link
 306      if ($link = $xpath->query(sprintf('//a[.="%s"]', $name))->item(0))
 307      {
 308        return $this->get($link->getAttribute('href'));
 309      }
 310  
 311      // image link
 312      if ($link = $xpath->query(sprintf('//a/img[@alt="%s"]/ancestor::a', $name))->item(0))
 313      {
 314        return $this->get($link->getAttribute('href'));
 315      }
 316  
 317      // form
 318      if (!$form = $xpath->query(sprintf('//input[((@type="submit" or @type="button") and @value="%s") or (@type="image" and @alt="%s")]/ancestor::form', $name, $name))->item(0))
 319      {
 320        throw new sfException(sprintf('Cannot find the "%s" link or button.', $name));
 321      }
 322  
 323      // form attributes
 324      $url = $form->getAttribute('action');
 325      $method = $form->getAttribute('method') ? strtolower($form->getAttribute('method')) : 'get';
 326  
 327      // merge form default values and arguments
 328      $defaults = array();
 329      foreach ($xpath->query('descendant::input | descendant::textarea | descendant::select', $form) as $element)
 330      {
 331        $elementName = $element->getAttribute('name');
 332        $nodeName    = $element->nodeName;
 333        $value       = null;
 334        if ($nodeName == 'input' && ($element->getAttribute('type') == 'checkbox' || $element->getAttribute('type') == 'radio'))
 335        {
 336          if ($element->getAttribute('checked'))
 337          {
 338            $value = $element->getAttribute('value');
 339          }
 340        }
 341        else if (
 342          $nodeName == 'input'
 343          &&
 344          (($element->getAttribute('type') != 'submit' && $element->getAttribute('type') != 'button') || $element->getAttribute('value') == $name)
 345          &&
 346          ($element->getAttribute('type') != 'image' || $element->getAttribute('alt') == $name)
 347        )
 348        {
 349          $value = $element->getAttribute('value');
 350        }
 351        else if ($nodeName == 'textarea')
 352        {
 353          $value = '';
 354          foreach ($element->childNodes as $el)
 355          {
 356            $value .= $dom->saveXML($el);
 357          }
 358        }
 359        else if ($nodeName == 'select')
 360        {
 361          if ($multiple = $element->hasAttribute('multiple'))
 362          {
 363            $elementName = str_replace('[]', '', $elementName);
 364            $value = array();
 365          }
 366          else
 367          {
 368            $value = null;
 369          }
 370  
 371          $found = false;
 372          foreach ($xpath->query('descendant::option', $element) as $option)
 373          {
 374            if ($option->getAttribute('selected'))
 375            {
 376              $found = true;
 377              if ($multiple)
 378              {
 379                $value[] = $option->getAttribute('value');
 380              }
 381              else
 382              {
 383                $value = $option->getAttribute('value');
 384              }
 385            }
 386          }
 387  
 388          // if no option is selected and if it is a simple select box, take the first option as the value
 389          if (!$found && !$multiple)
 390          {
 391            $value = $xpath->query('descendant::option', $element)->item(0)->getAttribute('value');
 392          }
 393        }
 394  
 395        if (null !== $value)
 396        {
 397          $this->parseArgumentAsArray($elementName, $value, $defaults);
 398        }
 399      }
 400  
 401      // create request parameters
 402      $arguments = sfToolkit::arrayDeepMerge($defaults, $this->fields, $arguments);
 403      if ('post' == $method)
 404      {
 405        return $this->post($url, $arguments);
 406      }
 407      else
 408      {
 409        $query_string = http_build_query($arguments);
 410        $sep = false === strpos($url, '?') ? '?' : '&';
 411  
 412        return $this->get($url.($query_string ? $sep.$query_string : ''));
 413      }
 414    }
 415  
 416    protected function parseArgumentAsArray($name, $value, &$vars)
 417    {
 418      if (false !== $pos = strpos($name, '['))
 419      {
 420        $var = &$vars;
 421        $tmps = array_filter(preg_split('/(\[ | \[\] | \])/x', $name));
 422        foreach ($tmps as $tmp)
 423        {
 424          $var = &$var[$tmp];
 425        }
 426        if ($var)
 427        {
 428          if (!is_array($var))
 429          {
 430            $var = array($var);
 431          }
 432          $var[] = $value;
 433        }
 434        else
 435        {
 436          $var = $value;
 437        }
 438      }
 439      else
 440      {
 441        $vars[$name] = $value;
 442      }
 443    }
 444  
 445    public function restart()
 446    {
 447      $this->newSession();
 448      $this->cookieJar     = array();
 449      $this->stack         = array();
 450      $this->fields        = array();
 451      $this->vars          = array();
 452      $this->dom           = null;
 453      $this->stackPosition = -1;
 454  
 455      return $this;
 456    }
 457  
 458    public function shutdown()
 459    {
 460      // we remove all session data
 461      sfToolkit::clearDirectory(sfConfig::get('sf_test_cache_dir').'/sessions');
 462    }
 463  
 464    protected function fixUri($uri)
 465    {
 466      // remove absolute information if needed (to be able to do follow redirects, click on links, ...)
 467      if (0 === strpos($uri, 'http'))
 468      {
 469        // detect secure request
 470        if (0 === strpos($uri, 'https'))
 471        {
 472          $this->defaultServerArray['HTTPS'] = 'on';
 473        }
 474        else
 475        {
 476          unset($this->defaultServerArray['HTTPS']);
 477        }
 478  
 479        $uri = substr($uri, strpos($uri, 'index.php') + strlen('index.php'));
 480      }
 481      $uri = str_replace('/index.php', '', $uri);
 482  
 483      // # as a uri
 484      if ($uri && '#' == $uri[0])
 485      {
 486        $uri = $this->stack[$this->stackPosition]['uri'].$uri;
 487      }
 488  
 489      return $uri;
 490    }
 491  
 492    protected function newSession()
 493    {
 494      $_SERVER['session_id'] = md5(uniqid(rand(), true));
 495    }
 496  }
 497  
 498  class sfFakeRenderingFilter extends sfFilter
 499  {
 500    public function execute($filterChain)
 501    {
 502      $filterChain->execute();
 503  
 504      $this->getContext()->getResponse()->sendContent();
 505    }
 506  }


Généré le : Fri Mar 16 22:42:14 2007 par Balluche grâce à PHPXref 0.7