ソースを参照

Hello static pages

markseu 11 年 前
コミット
1f2b81f1d2
2 ファイル変更118 行追加42 行削除
  1. 79 33
      system/core/core-commandline.php
  2. 39 9
      system/core/core.php

+ 79 - 33
system/core/core-commandline.php

@@ -5,9 +5,13 @@
 // Command line core plugin
 class YellowCommandline
 {
-	const Version = "0.2.3";
+	const Version = "0.2.4";
 	var $yellow;			//access to API
-
+	var $content;			//number of content pages
+	var $error;				//number of build errors
+	var $locationsArgs;		//build locations with arguments
+	var $locationsPage;		//build locations with pagination
+	
 	// Initialise plugin
 	function onLoad($yellow)
 	{
@@ -81,11 +85,12 @@ class YellowCommandline
 		return $statusCode;
 	}
 	
-	// Build static files
+	// Build static locations and files
 	function buildStatic($location, $path)
 	{
 		$this->yellow->toolbox->timerStart($time);
-		$statusCodeMax = $error = 0;
+		$this->content = $this->error = $statusCodeMax = 0;
+		$this->locationsArgs = $this->locationsPage = array();
 		if(empty($location))
 		{
 			$pages = $this->yellow->pages->index(true);
@@ -102,26 +107,36 @@ class YellowCommandline
 		}
 		foreach($pages as $page)
 		{
-			$statusCode = $this->buildStaticLocation($page->location, $path);
-			$statusCodeMax = max($statusCodeMax, $statusCode); if($statusCode >= 400) ++$error;
+			$statusCodeMax = max($statusCodeMax, $this->buildStaticLocation($page->location, $path, empty($location)));
+		}
+		foreach($this->locationsArgs as $location)
+		{
+			$statusCodeMax = max($statusCodeMax, $this->buildStaticLocation($location, $path, true));
+		}
+		foreach($this->locationsPage as $location)
+		{
+			for($pageNumber=2; $pageNumber<=999; ++$pageNumber)
+			{
+				$statusCode = $this->buildStaticLocation($location.$pageNumber, $path, false, true);
+				$statusCodeMax = max($statusCodeMax, $statusCode);
+				if($statusCode == 0) break;
+			}
 		}
 		foreach($fileNamesMedia as $fileName)
 		{
-			$statusCode = $this->buildStaticFile($fileName, "$path/$fileName", "media file");
-			$statusCodeMax = max($statusCodeMax, $statusCode); if($statusCode >= 400) ++$error;
+			$statusCodeMax = max($statusCodeMax, $this->buildStaticFile($fileName, "$path/$fileName", "media file"));
 		}
 		foreach($fileNamesSystem as $fileName)
 		{
-			$statusCode = $this->buildStaticFile($fileName, "$path/$fileName", "system file");
-			$statusCodeMax = max($statusCodeMax, $statusCode); if($statusCode >= 400) ++$error;
+			$statusCodeMax = max($statusCodeMax, $this->buildStaticFile($fileName, "$path/$fileName", "system file"));
 		}
 		$this->yellow->toolbox->timerStop($time);
 		if(defined("DEBUG") && DEBUG>=1) echo "YellowCommandline::buildStatic time:$time ms\n";
-		return array($statusCodeMax, count($pages), count($fileNamesMedia), count($fileNamesSystem), $error);
+		return array($statusCodeMax, $this->content, count($fileNamesMedia), count($fileNamesSystem), $this->error);
 	}
 	
 	// Build static location
-	function buildStaticLocation($location, $path)
+	function buildStaticLocation($location, $path, $analyse = false, $probe = false)
 	{		
 		ob_start();
 		$_SERVER["SERVER_PROTOCOL"] = "HTTP/1.1";
@@ -144,23 +159,8 @@ class YellowCommandline
 				$fileOk = $this->yellow->toolbox->createFile($fileName, $fileData, true) &&
 					$this->yellow->toolbox->modifyFile($fileName, $modified);
 			} else {
-				if(!$this->yellow->toolbox->isFileLocation($location))
-				{
-					$fileName = $this->getStaticFileName($location, $path);
-					$fileData = $this->getStaticRedirect($staticLocation);
-					$fileOk = $this->yellow->toolbox->createFile($fileName, $fileData, true) &&
-						$this->yellow->toolbox->modifyFile($fileName, $modified);
-					if($fileOk)
-					{
-						$fileName = $this->getStaticFileName($staticLocation, $path);
-						$fileData = ob_get_contents();
-						$fileOk = $this->yellow->toolbox->createFile($fileName, $fileData, true) &&
-							$this->yellow->toolbox->modifyFile($fileName, $modified);
-					}
-				} else {
-					$statusCode = 409;
-					$this->yellow->page->error($statusCode, "Type '$contentType' does not match file name!");
-				}
+				$statusCode = 409;
+				$this->yellow->page->error($statusCode, "Type '$contentType' does not match file name!");
 			}
 			if(!$fileOk)
 			{
@@ -169,7 +169,14 @@ class YellowCommandline
 			}
 		}
 		ob_end_clean();
-		if($statusCode>=400) echo "ERROR building location '$location', ".$this->yellow->page->getStatusCode(true)."\n";
+		if($statusCode==200 && $analyse) $this->analyseStaticLocation($fileData);
+		if($statusCode==404 && $probe) $statusCode = 0;
+		if($statusCode != 0) ++$this->content;
+		if($statusCode >= 400)
+		{
+			++$this->error;
+			echo "ERROR building content location '$location', ".$this->yellow->page->getStatusCode(true)."\n";
+		}
 		if(defined("DEBUG") && DEBUG>=1) echo "YellowCommandline::buildStaticLocation status:$statusCode location:$location\n";
 		return $statusCode;
 	}
@@ -206,11 +213,50 @@ class YellowCommandline
 			}
 			ob_end_clean();
 		}
-		if($statusCode>=400) echo "ERROR building $fileType '$fileNameSource', ".$this->yellow->toolbox->getHttpStatusFormatted($statusCode)."\n";
+		if($statusCode >= 400)
+		{
+			++$this->error;
+			echo "ERROR building $fileType '$fileNameSource', ".$this->yellow->toolbox->getHttpStatusFormatted($statusCode)."\n";
+		}
 		if(defined("DEBUG") && DEBUG>=1) echo "YellowCommandline::buildStaticFile status:$statusCode file:$fileNameSource\n";
 		return $statusCode;
 	}
 	
+	// Analyse static location, detect links with arguments and pagination
+	function analyseStaticLocation($fileData)
+	{
+		$serverName = $this->yellow->config->get("serverName");
+		$serverBase = $this->yellow->config->get("serverBase");
+		preg_match_all("/<a(.*?)href=\"([^\"]+)\"(.*?)>/i", $fileData, $matches);
+		foreach($matches[2] as $match)
+		{
+			if(preg_match("/^\w+:\/+(.*?)(\/.*)$/", $match, $tokens))
+			{
+				if($tokens[1] != $serverName) continue;
+				$match = $tokens[2];
+			}
+			if(!$this->yellow->toolbox->isLocationArgs($match)) continue;
+			if(substru($match, 0, strlenu($serverBase)) != $serverBase) continue;
+			$match = rawurldecode(substru($match, strlenu($serverBase)));
+			if(!preg_match("/^(.*\/page:)\d*$/", $match, $tokens))
+			{
+				$match = rtrim($match, '/').'/';
+				if(is_null($this->locationsArgs[$match]))
+				{
+					$this->locationsArgs[$match] = $match;
+					if(defined("DEBUG") && DEBUG>=2) echo "YellowCommandline::analyseStaticLocation type:args location:$match\n";
+				}
+			} else {
+				$match = $tokens[1];
+				if(is_null($this->locationsPage[$match]))
+				{
+					$this->locationsPage[$match] = $match;
+					if(defined("DEBUG") && DEBUG>=2) echo "YellowCommandline::analyseStaticLocation type:page location:$match\n";
+				}
+			}
+		}
+	}
+	
 	// Return static location corresponding to content type
 	function getStaticLocation($location, $contentType)
 	{
@@ -221,12 +267,12 @@ class YellowCommandline
 			{
 				if($this->yellow->toolbox->isFileLocation($location))
 				{
-					if(!empty($extension) && $extension!=".html") $location .= ".html";
+					if(!empty($extension) && !preg_match("/^\.(html|md)$/", $extension)) $location .= ".html";
 				}
 			} else {
 				if($this->yellow->toolbox->isFileLocation($location))
 				{
-					if(empty($extension)) $location .= ".unknown";
+					if(empty($extension)) $location .= ".invalid";
 				} else {
 					if(preg_match("/^(\w+)\/(\w+)/", $contentType, $matches)) $extension = ".$matches[2]";
 					$location .= "index$extension";

+ 39 - 9
system/core/core.php

@@ -5,7 +5,7 @@
 // Yellow main class
 class Yellow
 {
-	const Version = "0.2.8";
+	const Version = "0.2.9";
 	var $page;				//current page data
 	var $pages;				//current page tree from file system
 	var $config;			//configuration
@@ -652,6 +652,7 @@ class YellowPage
 class YellowPageCollection extends ArrayObject
 {
 	var $yellow;				//access to API
+	var $filterValue;			//current page filter value
 	var $paginationPage;		//current page number in pagination
 	var $paginationCount;		//highest page number in pagination
 	
@@ -667,16 +668,20 @@ class YellowPageCollection extends ArrayObject
 		if(!empty($key))
 		{
 			$array = array();
-			$value = strtoloweru($value);
+			$value = strreplaceu(' ', '-', strtoloweru($value));
 			$valueLength = strlenu($value);
 			foreach($this->getArrayCopy() as $page)
 			{
 				if($page->isExisting($key))
 				{
-					foreach(preg_split("/,\s*/", strtoloweru($page->get($key))) as $valuePage)
+					foreach(preg_split("/,\s*/", $page->get($key)) as $pageValue)
 					{
-						$length = $exactMatch ? strlenu($valuePage) : $valueLength;
-						if($value == substru($valuePage, 0, $length)) array_push($array, $page);
+						$pageValueLength = $exactMatch ? strlenu($pageValue) : $valueLength;
+						if($value == substru(strreplaceu(' ', '-', strtoloweru($pageValue)), 0, $pageValueLength))
+						{
+							$this->filterValue = $pageValue;
+							array_push($array, $page);
+						}
 					}
 				}
 			}
@@ -788,6 +793,12 @@ class YellowPageCollection extends ArrayObject
 		return $this->getLocationPage($pageNumber);
 	}
 	
+	// Return current page filter
+	function getFilter()
+	{
+		return $this->filterValue;
+	}
+	
 	// Return last modification time for page collection, Unix time
 	function getModified($httpFormat = false)
 	{
@@ -1272,7 +1283,7 @@ class YellowToolbox
 		if(!empty($locationArgs))
 		{
 			if($this->isFileLocation($location)) $locationArgs = '/'.$locationArgs;
-			$locationArgs = strreplaceu(array('%3A','%2F'), array(':','/'), rawurlencode($locationArgs));
+			$locationArgs = $this->normaliseLocationArgs($locationArgs, false);
 		}
 		return $locationArgs;
 	}
@@ -1293,7 +1304,7 @@ class YellowToolbox
 		if(!empty($locationArgs))
 		{
 			if($this->isFileLocation($location)) $locationArgs = '/'.$locationArgs;
-			$locationArgs = strreplaceu(array('%3A','%2F'), array(':','/'), rawurlencode($locationArgs));
+			$locationArgs = $this->normaliseLocationArgs($locationArgs, false);
 		}
 		return $locationArgs;
 	}
@@ -1408,12 +1419,30 @@ class YellowToolbox
 		return $location;
 	}
 	
-	// Normalise directory/file name and convert unwanted characters
+	// Normalise location arguments
+	function normaliseLocationArgs($text, $lowerCase = true)
+	{
+		if($lowerCase) $text = strreplaceu(' ', '-', strtoloweru($text));
+		if(!preg_match("/^(.*\/)?page:\d*$/", $text)) $text .= '/';
+		return strreplaceu(array('%3A','%2F'), array(':','/'), rawurlencode($text));
+	}
+	
+	// Normalise directory/file name
 	function normaliseName($text, $removeExtension = false)
 	{
 		if(preg_match("/^[\d\-\_\.]+(.*)$/", $text, $matches)) $text = $matches[1];
 		if($removeExtension) $text = ($pos = strrposu($text, '.')) ? substru($text, 0, $pos) : $text;
-		$text = preg_replace("/[^\pL\d\-\_\.]/u", "-", $text);
+		return preg_replace("/[^\pL\d\-\_\.]/u", "-", $text);
+	}
+	
+	// Normalise text into UTF-8 NFC
+	function normaliseUnicode($text)
+	{
+		if(PHP_OS=="Darwin" && !mb_check_encoding($text, "ASCII"))
+		{
+			$utf8nfc = preg_match("//u", $text) && !preg_match('/[^\x00-\x{2FF}]/u', $text);
+			if(!$utf8nfc) $text = iconv("UTF-8-MAC", "UTF-8", $text);
+		}
 		return $text;
 	}
 	
@@ -1480,6 +1509,7 @@ class YellowToolbox
 			while(($entry = readdir($dirHandle)) !== false)
 			{
 				if(substru($entry, 0, 1) == ".") continue;
+				$entry = $this->normaliseUnicode($entry);
 				if(preg_match($regex, $entry))
 				{
 					if($directories)