<?php

/**
 * @copyright (c) Kufer Software GmbH, Loisachstrasse 4, D-84453 Mühldorf
 */


class URL
{
  
  protected $parameters;

  
  protected $protocol;

  
  protected $server;

  
  protected $host;

  
  protected $port;

  
  protected $path;


  
  protected $file;


  
  protected $anchor;

  
  public function __construct($pFullUrl)
  {
    $this->load($pFullUrl);
  }

  
  public function load($pFullUrl)
  {
    if ($pFullUrl == '') {
      throw new Exception('Der Parameter $pFullUrl darf nicht leer sein.');
    }

    

    $splitUrlArray = explode('?', $pFullUrl, 2);

    $this->parameters = array();

    if (count($splitUrlArray) > 1 && StringOperations::strlen($splitUrlArray[1]) > 0) {
      $parameterValueStringArray = explode('&', $splitUrlArray[1]);
      foreach ($parameterValueStringArray as $parameterValueString) {
        $parameterValueArray = explode('=', $parameterValueString);
        if (isset($parameterValueArray[1]) && \StringOperations::substr_count($parameterValueArray[1], '#') === 1) {
          $splittmp = explode('#', $parameterValueArray[1], 2);
          if (StringOperations::endsWith($parameterValueArray[0], '[]')) {
            if (!isset($this->parameters[$parameterValueArray[0]])) {
              $this->parameters[$parameterValueArray[0]] = array();
            }
            $this->parameters[$parameterValueArray[0]][] = $splittmp[0];
            $this->anchor = $splittmp[1];
          } else {
            $this->parameters[$parameterValueArray[0]] = $splittmp[0];
            $this->anchor = $splittmp[1];
          }
        } else {
          if (StringOperations::endsWith($parameterValueArray[0], '[]')) {
            if (!isset($this->parameters[$parameterValueArray[0]])) {
              $this->parameters[$parameterValueArray[0]] = array();
            }
            $this->parameters[$parameterValueArray[0]][] = $parameterValueArray[1];
          } else {
            $this->parameters[$parameterValueArray[0]] = (isset($parameterValueArray[1]) ? $parameterValueArray[1] : ''); 
          }
        }
      }
    }

    $protocolPathSplit = array();
    if (StringOperations::strpos($splitUrlArray[0], '://') !== false) {
      $protocolPathSplit = explode('://', $splitUrlArray[0], 2);
    } else {
      $protocolPathSplit[0] = 'http';
      $protocolPathSplit[1] = $splitUrlArray[0];
    }
    $this->protocol = $protocolPathSplit[0];

    $serverRequestSplit = explode('/', $protocolPathSplit[1], 2);

    $this->server = $serverRequestSplit[0];
    if (StringOperations::contains($this->server, ':')) {
      $hostPort = explode(':', $this->server, 2);
      $this->host = $hostPort[0];
      $this->port = $hostPort[1];
    }

    isset($serverRequestSplit[1]) ? $path = explode('/', $serverRequestSplit[1]) : $path = array('');

    $this->path = array();
    $count = count($path);
    for ($i = 0; $i < $count; ++$i) {
      $item = $path[$i];
      if ($i == ($count - 1) && (StringOperations::strpos($item, '.') !== false)
      || StringOperations::stripos($item, INDEXSCRIPT) !== false) {
        
        

        if (StringOperations::contains($item, '#')) {
          $splittmp = explode('#', $item, 2);
          $this->file = $splittmp[0];
          $this->anchor = $splittmp[1];
        } else {
          $this->file = $item;
        }
        break;
      } else {
        if ($item != '') {
          $this->path[] = $item;
        }
      }
    }
  }

  
  public static function loadCurrent()
  {
    $protocol = 'http';
    if (isset($_SERVER['HTTPS'])) {
      $protocol = 'https';
    }
    $url = $protocol . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];

    return new URL($url);
  }

  
  public function cleanParameter()
  {
    $temp = array();
    foreach ($this->parameters as $parameter => $value) {
      if (!array_key_exists($parameter, $temp)) {
        $temp[$parameter] = $value;
      }
    }
    $this->parameters = $temp;
  }

  
  public function setParameterValue($pParameter, $pValue)
  {
    $this->parameters[$pParameter] = $pValue;
  }

  
  public function getParameterValue($pParameter)
  {
    return isset($this->parameters[$pParameter]) ? $this->parameters[$pParameter] : null;
  }

  
  public function getAllParameters()
  {
    return $this->parameters;
  }

  
  public function setAllParameters($pParameters)
  {
    $this->parameters = $pParameters;
  }

  
  public function hasParameter($pParameter)
  {
    return array_key_exists($pParameter, $this->parameters);
  }

  
  public function removeParameter($pParameter)
  {
    unset($this->parameters[$pParameter]);
  }

  
  public function removeSpecialParametersFromUrl()
  {
    if ($this->hasParameter('markerAction')) {
      if ($this->getParameterValue('markerAction') == 'loescheMarkierungen') {
        $this->removeParameter('idsToMark'); 
      }
      $this->removeParameter('markerAction'); 
    }

    if ($this->hasParameter('history')) {
      $this->removeParameter('history');   
    }
  }

  
  public function hasFile()
  {
    return $this->file != '';
  }

  
  public function getFile()
  {
    return $this->file;
  }

  
  public function setFile($pFile)
  {
    $this->file = $pFile;
  }

  
  public function getServer()
  {
    return $this->server;
  }

  
  public function setServer($pServer)
  {
    $this->server = $pServer;
  }

  
  public function getProtocol()
  {
    return $this->protocol;
  }

  
  public function setProtocol($pProtocol)
  {
    $this->protocol = $pProtocol;
  }

  
  public function getPath()
  {
    return $this->path;
  }

  
  public function setPath($pPath)
  {
    $this->path = $pPath;
  }

  
  public function addPathSegment($pSegment)
  {
    if (!is_array($this->path)) {
      $this->path = array();
    }
    if (is_array($pSegment)) {
      foreach ($pSegment as $segment) {
        $this->addPathSegment($segment);
      }
    } else {
      $parts = explode('/', $pSegment);
      if (count($parts) > 0) {
        foreach ($parts as $segment) {
          if ($segment != '') {
            $this->path[] = $segment;
          }
        }
      }
    }
  }

  
  public function getAnchor()
  {
    return $this->anchor;
  }

  
  public function setAnchor($pAnchor)
  {
    $this->anchor = $pAnchor;
  }

  
  public function getHost()
  {
    return $this->host;
  }

  
  public function getPort()
  {
    return $this->port;
  }

  
  public function previousDir()
  {
    $clone = clone $this;
    $path = $clone->path;
    $count = count($path);
    if ($count > 0) {
      unset($path[$count - 1]);
    }
    $clone->setPath($path);
    $clone->setAllParameters(array());
    $clone->setFile(null);
    $clone->setAnchor(null);

    return $clone;
  }

  
  public function dirOnly()
  {
    return new URL($this->toString(false, false, false));
  }

  
  public function getUrlFull($pWithProtocol = true, $pWithParameters = true, $pWithAnchor = true)
  {
    $return = $this->getDirectory($pWithProtocol, true);
    $return .= $this->getUrlRelative($pWithParameters, $pWithAnchor);

    return $return;
  }

  
  public function getUrlRelative($pWithParameters = true, $pWithAnchor = true)
  {
    $return = $this->file;

    if ($pWithParameters) {
      $tmp = array();
      foreach ($this->parameters as $param => $value) {
        if ($value != '') {
          if (is_array($value)) {
            foreach ($value as $v) {
              $tmp[] = $param . '=' . $v;
            }
          } else {
            $tmp[] = $param . '=' . $value;
          }
        }
      }
      $parameterString = implode('&', $tmp);

      if ($parameterString != '') {
        $return .= '?' . $parameterString;
      }
    }

    if ($pWithAnchor && ($this->anchor != '')) {
      $return .= '#' . $this->anchor;
    }
    
    
    
    if (is_null($return)) {
      $return = 'usertools.php';
    }

    return $return;
  }

  
  public function hasSameParameters($pOtherUrl, $pExcludeParameters = array())
  {
    foreach ($pOtherUrl->getAllParameters() as $parameter => $value) {
      if (in_array($parameter, $pExcludeParameters)) {
        continue;
      }
      if (!$this->hasParameter($parameter) || ($this->getParameterValue($parameter) !== $value)) {
        return false;
      }
    }

    return true;
  }

  
  public function getDirectory($pWithProtocol = true, $pWithSlashAtEnd = false)
  {
    $return = '';

    if ($pWithProtocol) {
      $return .= $this->protocol . '://';
    }

    $tmp = '';
    foreach ($this->path as $p) {
      $tmp .= '/' . $p;
    }
    $tmp = $this->server . $tmp;

    $return .= $tmp;

    if ($pWithSlashAtEnd) {
      $return .= '/';
    }

    return $return;
  }

  
  public function toString($pWithFile = true, $pWithParameters = true, $pWithAnchor = true)
  {
    $return = $this->protocol . '://';

    $tmp = '';
    foreach ($this->path as $p) {
      $tmp .= '/' . $p;
    }
    $tmp = $this->server . $tmp;

    $return .= $tmp;

    if ($pWithFile && ($this->file != '')) {
      $return .= '/' . $this->file;
    }

    $tmp = array();
    foreach ($this->parameters as $param => $value) {
      if ($value != '') {
        if (is_array($value)) {
          foreach ($value as $v) {
            $tmp[] = $param . '=' . $v;
          }
        } else {
          $tmp[] = $param . '=' . $value;
        }
      }
    }
    $parameterString = implode('&', $tmp);

    if ($pWithParameters && ($parameterString != '')) {
      $return .= '?' . $parameterString;
    }

    if ($pWithAnchor && ($this->anchor != '')) {
      $return .= '#' . $this->anchor;
    }

    return $return;
  }
}