From 29a026e71a6487d5d954adcf7bb6a76e5338345c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Sun, 5 Feb 2012 17:42:53 +0100
Subject: [PATCH] Improved URL rewriting support

When this code was written, it did not include an internal URL mapper
and each page was loaded by a PHP script. The internal URL was a recent,
mostly unfinished addition.

Base URL is now supported:
 * for views, when they implement the BaseURLAware interface (a base
class that does what most views will do with that is provided -
BaseURLAwareView),
 * in the menu,
 * in form actions,
 * in boxes (for buttons, and for the contents if the inner view
implements BaseURLAware).
---
 includes/box/view.inc.php  | 26 +++++++++++++++++++++-----
 includes/core/page.inc.php |  8 +++++++-
 includes/core/view.inc.php | 23 +++++++++++++++++++++++
 includes/form/ctrl.inc.php | 10 ++++++++--
 includes/form/view.inc.php | 12 ++++++++++--
 5 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/includes/box/view.inc.php b/includes/box/view.inc.php
index dcd3f1f..786c006 100644
--- a/includes/box/view.inc.php
+++ b/includes/box/view.inc.php
@@ -32,11 +32,18 @@ class BoxButton
 		return $this;
 	}
 
-	public function render( )
+	public function render( $baseURL )
 	{
+		$url = $this->URL;
+		if ( $url{0} != ':' ) {
+			if ( $url{0} != '/' ) {
+				$url = "/$url";
+			}
+			$url = $baseURL . $url;
+		}
 		return HTML::make( 'a' )
 			->setAttribute( 'title' , HTML::from( $this->title ) )
-			->setAttribute( 'href' , $this->URL )
+			->setAttribute( 'href' , $url )
 			->setAttribute( 'class' ,
 				'box-button' . ( ( $this->class === null )
 					? '' : ( ' ' . $this->class ) ) )
@@ -54,8 +61,8 @@ class BoxButton
 }
 
 
-final class View_Box
-	implements View
+class View_Box
+	extends BaseURLAwareView
 {
 	protected $title;
 	protected $class;
@@ -72,6 +79,15 @@ final class View_Box
 	}
 
 
+	public function setBaseURL( $baseURL )
+	{
+		parent::setBaseURL( $baseURL );
+		if ( $this->contents instanceof BaseURLAware ) {
+			$this->contents->setBaseURL( $baseURL );
+		}
+	}
+
+
 	public function setClass( $class )
 	{
 		$this->class = $class;
@@ -110,7 +126,7 @@ final class View_Box
 			$buttons = HTML::make( 'div' )
 				->setAttribute( 'class' , 'box-buttons' );
 			foreach ( $this->buttons as $button ) {
-				$buttons->appendElement( $button->render( ) );
+				$buttons->appendElement( $button->render( $this->base ) );
 			}
 			$box->appendElement( $buttons );
 		}
diff --git a/includes/core/page.inc.php b/includes/core/page.inc.php
index 5c6218e..b9a5b47 100644
--- a/includes/core/page.inc.php
+++ b/includes/core/page.inc.php
@@ -49,6 +49,9 @@ abstract class Page
 				}
 			}
 		} elseif ( ! is_null( $rc ) ) {
+			if ( $rc{0} != '/' ) {
+				$rc = $this->baseURL . '/' . $rc;
+			}
 			header( "Location: $rc" );
 			$rv = true;
 		}
@@ -121,7 +124,7 @@ abstract class HTMLPage
 		foreach ( $menu as $link => $title ) {
 			$html->appendElement( HTML::make( 'li' )
 				->appendElement( HTML::make( 'a' )
-					->setAttribute( 'href' , $link )
+					->setAttribute( 'href' , $this->getBaseURL() . '/' . $link )
 					->setAttribute( 'title' , HTML::from( $title ) )
 					->appendText( $title ) ) );
 		}
@@ -170,6 +173,9 @@ abstract class HTMLPage
 		}
 
 		foreach ( $this->views as $view ) {
+			if ( $view instanceof BaseURLAware ) {
+				$view->setBaseURL( $this->getBaseURL( ) );
+			}
 			$container->append( $view->render( ) );
 		}
 
diff --git a/includes/core/view.inc.php b/includes/core/view.inc.php
index 5ccd0e5..5ec510c 100644
--- a/includes/core/view.inc.php
+++ b/includes/core/view.inc.php
@@ -5,6 +5,29 @@ interface View
 	public function render( );
 }
 
+interface BaseURLAware
+{
+	public function setBaseURL( $baseURL );
+}
+
+abstract class BaseURLAwareView
+	implements View , BaseURLAware
+{
+	protected $base;
+
+	public function setBaseURL( $baseURL )
+	{
+		$this->base = $baseURL;
+	}
+}
+
+interface TitleProvider
+{
+
+	public function getTitle( );
+
+}
+
 
 final class HTML
 {
diff --git a/includes/form/ctrl.inc.php b/includes/form/ctrl.inc.php
index 9c8a338..d838213 100644
--- a/includes/form/ctrl.inc.php
+++ b/includes/form/ctrl.inc.php
@@ -65,9 +65,15 @@ class Ctrl_Form
 			return $this->form->view( );
 		}
 		if ( $cResult ) {
-			return $this->form->successURL( );
+			$url = $this->form->successURL( );
+		} else {
+			$url = $this->form->cancelURL( );
 		}
-		return $this->form->cancelURL( );
+
+		if ( $url{0} != '/' ) {
+			$url = "/$url";
+		}
+		return $page->getBaseURL( ) . $url;
 	}
 
 }
diff --git a/includes/form/view.inc.php b/includes/form/view.inc.php
index 500f00c..aa6c91e 100644
--- a/includes/form/view.inc.php
+++ b/includes/form/view.inc.php
@@ -1,7 +1,7 @@
 <?php
 
 class View_Form
-	implements View
+	extends BaseURLAwareView
 {
 	protected $form;
 
@@ -161,10 +161,18 @@ class View_Form
 		$name = $this->form->name();
 		$prefix = $name . '-';
 
+		$action = $this->form->action( );
+		if ( $action{0} != '?' ) {
+			if ( $action{0} != '/' ) {
+				$action = "/$action";
+			}
+			$action = $this->base . $action;
+		}
+
 		$form = HTML::make( 'form' )
 			->setAttribute( 'name' , $name )
 			->setAttribute( 'id' , $prefix . 'form' )
-			->setAttribute( 'action' , $this->form->action( ) )
+			->setAttribute( 'action' , $action )
 			->setAttribute( 'method' , $this->form->method( ) )
 			->append( $this->renderHiddenFields( $prefix ) )
 			->append( $visibleArea = HTML::make( 'dl' ) );