Nested URL's

adds nested URL functionality to SilverStripe and Sapphire.

Note: Theres a newer, changing version available here

Diff: (see below to download)

trunk/sapphire/core/control/Director.php

39
39
 	static $test_servers = array();
40
40
 	
41
41
 	static protected $environment_type;
 
42
+	
 
43
+	protected static $fullUrl;
42
44
 
43
45
 	/** 
44
46
 	 * Sets the site mode (if it is the public site or the cms), 
91
91
 	 */
92
92
 	function direct($url) {
93
93
 		if(isset($_GET['debug_profile'])) Profiler::mark("Director","direct");
 
94
+		self::$fullUrl = $url;
94
95
 		$controllerObj = Director::getControllerForURL($url);
95
96
 		
96
97
 		if(is_string($controllerObj) && substr($controllerObj,0,9) == 'redirect:') {
689
689
 		
690
690
 		return false;
691
691
 	}
 
692
+	
 
693
+	/**
 
694
+	 * Returns the full URL as requested
 
695
+	 *
 
696
+	 * @return string
 
697
+	 */
 
698
+	public static function getUrl(){
 
699
+		return self::$fullUrl == '/' ? RootURLController::get_homepage_urlsegment() : self::$fullUrl;
 
700
+	}
692
701
 
693
702
 	/**
694
703
 	 * @deprecated use isDev() instead

trunk/sapphire/core/control/ContentController.php

34
34
 	public function __construct($dataRecord) {
35
35
 		$this->dataRecord = $dataRecord;
36
36
 		$this->failover = $this->dataRecord;
 
37
+		
 
38
+		//So we have the correct Page ID
 
39
+		$this->dataRecord->setCurrentPageID($this->dataRecord->ID);
 
40
+		
 
41
+		//And the correct Section IDs
 
42
+		$currentSections = array();
 
43
+		$nextID = $this->dataRecord->ID;
 
44
+		while($nextID) {
 
45
+			$currentSections[] = $nextID;
 
46
+			$nextID = DB::query("SELECT ParentID FROM SiteTree WHERE ID = $nextID")->value();
 
47
+		}
 
48
+		
 
49
+		$this->dataRecord->setCurrentPageIDs($currentSections);
37
50
 
38
51
 		parent::__construct();
39
52
 	}

trunk/sapphire/core/control/ModelAsController.php

36
36
 	}
37
37
 
38
38
 	public function getNestedController() {
39
 
-		if($this->urlParams['URLSegment']) {
40
 
-			$SQL_URLSegment = Convert::raw2sql($this->urlParams['URLSegment']);
41
 
-			if (Translatable::is_enabled()) {
42
 
-				$child = Translatable::get_one("SiteTree", "URLSegment = '$SQL_URLSegment'");
43
 
-			} else {
44
 
-				$child = DataObject::get_one("SiteTree", "URLSegment = '$SQL_URLSegment'");
45
 
-			}
46
 
-			if(!$child) {
47
 
-				$child = $this->get404Page();
48
 
-			}
 
39
+		//strip lead and end slashes
 
40
+		$url = preg_replace(array('/^\//', '/\/$/'), '', Director::getUrl());
 
41
+		$segments = explode('/', $url);
49
42
 		
50
 
-			if($child) {
51
 
-				if(isset($_REQUEST['debug'])) Debug::message("Using record #$child->ID of type $child->class with URL {$this->urlParams['URLSegment']}");
52
 
-				
53
 
-				$controllerClass = "{$child->class}_Controller";
54
 
-	
55
 
-				if($this->urlParams['Action'] && ClassInfo::exists($controllerClass.'_'.$this->urlParams['Action'])) {
56
 
-					$controllerClass = $controllerClass.'_'.$this->urlParams['Action'];	
 
43
+		$SQL_URLSegment = Convert::raw2sql($segments[0]);
 
44
+		if(Translatable::is_enabled()){
 
45
+			$model = Translatable::get_one('SiteTree', 'URLSegment = \'' . $SQL_URLSegment . '\'');
 
46
+		} else {
 
47
+			$model = DataObject::get_one('SiteTree', 'URLSegment = \'' . $SQL_URLSegment . '\'');
 
48
+		}			
 
49
+		
 
50
+		if($model){
 
51
+			
 
52
+			$segment = 1;
 
53
+			if(Translatable::is_enabled()){
 
54
+				while(isset($segments[$segment]) && $obj = Translatable::get_one('SiteTree', 'URLSegment = \'' . Convert::raw2sql($segments[$segment]) . 
 
55
+					'\' AND ParentID = ' . $model->ID)){
 
56
+					$model = $obj;
 
57
+					$segment++;
57
58
 				}
58
 
-	
59
 
-				if(ClassInfo::exists($controllerClass)) {
60
 
-					$controller = new $controllerClass($child);
61
 
-				} else {
62
 
-					$controller = $child;
 
59
+			} else {
 
60
+				while(isset($segments[$segment]) && $obj = DataObject::get_one('SiteTree', 'URLSegment = \'' . Convert::raw2sql($segments[$segment]) . 
 
61
+					'\' AND ParentID = ' . $model->ID)){
 
62
+					$model = $obj;
 
63
+					$segment++;
63
64
 				}
64
 
-				$controller->setURLParams($this->urlParams);
 
65
+			}
65
66
 			
66
 
-				return $controller;
67
 
-			} else {
68
 
-				return "The requested page couldn't be found.";
 
67
+			if(isset($_REQUEST['debug'])) Debug::message("Using record #$model->ID of type $model->class - routed from $url");
 
68
+			
 
69
+			$controllerClass = "{$model->class}_Controller";
 
70
+			
 
71
+			$segment--;
 
72
+			foreach($this->urlParams as $key=>$param){
 
73
+				$this->urlParams[$key] = isset($segments[$segment]) ? $segments[$segment] : NULL;
 
74
+				$segment++;
69
75
 			}
70
76
 			
 
77
+			if($this->urlParams['Action'] && ClassInfo::exists($controllerClass.'_'.$this->urlParams['Action'])) {
 
78
+				$controllerClass = $controllerClass.'_'.$this->urlParams['Action'];	
 
79
+			}
 
80
+			
 
81
+			$controller = ClassInfo::exists($controllerClass) ? new $controllerClass($model) : $model;
 
82
+			$controller->setURLParams($this->urlParams);
 
83
+			
 
84
+			return $controller;
71
85
 		} else {
72
 
-			user_error("ModelAsController not geting a URLSegment.  It looks like the site isn't redirecting to home", E_USER_ERROR);
 
86
+			$model = $this->get404Page();
73
87
 		}
74
88
 	}
75
89
 	

trunk/sapphire/core/model/SiteTree.php

391
391
 			}
392
392
 		}
393
393
 	}
 
394
+	
 
395
+	/**
 
396
+	 * Set the curent page ID
 
397
+	 *
 
398
+	 * @param int ID
 
399
+	 * @return void
 
400
+	 */
 
401
+	public function setCurrentPageID($id){
 
402
+		self::$currentPageID = (int) $id;
 
403
+	}
 
404
+	
 
405
+	/**
 
406
+	 * Sets the current Section IDs
 
407
+	 *
 
408
+	 * @param array $sections
 
409
+	 * @return void
 
410
+	 */
 
411
+	public function setCurrentPageIDs($sections){
 
412
+		self::$currentSectionIDs = $sections;
 
413
+	}
394
414
 
395
415
 
396
416
 	/**
1097
1097
 					),
1098
1098
 					$tabMeta = new Tab('Meta-data',
1099
1099
 						new FieldGroup(_t('SiteTree.URL', "URL"),
1100
 
-							new LabelField("http://www.yoursite.com/"),
 
1100
+							new LabelField("http://www.yoursite.com/" . $this->getURLBase()),
1101
1101
 							//new TextField("URLSegment",""),
1102
1102
 							new UniqueRestrictedTextField("URLSegment",
1103
1103
 								"URLSegment",
1514
1514
 		return $classes;
1515
1515
 	}
1516
1516
 
 
1517
+	/**
 
1518
+	 * Overrides URLSegment, returns the URL Segment along with all nested
 
1519
+	 * parent information
 
1520
+	 * 
 
1521
+	 * @return string
 
1522
+	 */
 
1523
+	public function getURLSegment(){
 
1524
+		//if in CMS mode we need only the editable part
 
1525
+		if(Director::get_site_mode() == 'cms') return $this->getField('URLSegment');
 
1526
+		
 
1527
+		return $this->getURLBase() . $this->getField('URLSegment');
 
1528
+	}
 
1529
+	
 
1530
+	/**
 
1531
+	 * Returns the nested URL for this SiteTree, without the actual URLSegment
 
1532
+	 *
 
1533
+	 * @return string
 
1534
+	 */
 
1535
+	public function getURLBase(){
 
1536
+		$model = $this;
 
1537
+		$urlChain = '';
 
1538
+		while($model = $model->getParent()) $urlChain = $model->getField('URLSegment') . '/' . $urlChain;
 
1539
+		
 
1540
+		return $urlChain;
 
1541
+	}
1517
1542
 }
1518
1543
 ?>
1519
1544

Download Diff