Hello world

This commit is contained in:
markseu 2013-04-07 20:04:09 +02:00
parent f42d94c9f4
commit 9355317b5e
20 changed files with 3967 additions and 3 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.DS_Store

13
.htaccess Normal file
View file

@ -0,0 +1,13 @@
# Yellow .htaccess
<IfModule mod_rewrite.c>
RewriteEngine on
# RewriteBase /yellow
RewriteRule ^content/(.*) error [R=301,L]
RewriteRule ^system/(.*) error [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+) index.php [L]
</IfModule>

View file

@ -1,4 +1,4 @@
yellowcms
=========
Yellow
======
CMS for people, web-based and flat-file
Yellow is a CMS for people, it's web-based and flat-file.

7
content/1-home/page.txt Executable file
View file

@ -0,0 +1,7 @@
---
Title: Home
---
Yes, it works! Your Yellow installation was successful.
You can now [edit this page](wiki/) or use your favorite text editor.
[Visit Yellow on Github](https://github.com/markseu/yellowcms).

4
content/2-services/page.txt Executable file
View file

@ -0,0 +1,4 @@
---
Title: Services
---
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna pizza. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

4
content/3-about/page.txt Executable file
View file

@ -0,0 +1,4 @@
---
Title: About
---
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna pizza. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

5
index.php Normal file
View file

@ -0,0 +1,5 @@
<?php
require_once("system/core/core.php");
$yellow = new Yellow();
$yellow->request();
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,14 @@
html, body { margin:0px; padding:0px; }
body { width:600px; margin:50px auto; font-family:"Helvetica Neue",Helvetica,sans-serif; background:#fff; color:#777; }
a { text-decoration:none; color:#05d; }
a:hover { text-decoration:none; color:#f00; }
h1, h2, h3, h4, h5, h6 { font-weight:normal; color:#111; }
h1 { font-size:1.5em; }
p, ul { line-height:1.5; }
img { vertical-align:top; }
.header a { font-size:2.0em; color:#111; }
.navigation { margin-top:1em; margin-bottom:1em; padding-bottom:1em; border-bottom:solid 2px #ec0; font-size:1.2em; font-weight:bold; }
.navigation ul { list-style:none; margin:0px; padding:0px; }
.navigation li { display:inline; margin-right:1em; }
.navigation li a.active { color: red; }
.footer { margin-top:2em; padding-top:1em; border-top:solid 2px #ec0; }

View file

@ -0,0 +1,2 @@
body, h1, h2, h3, h4, h5, h6 { background:white; color:black; }
.navigation, .footer { display:none !important; }

24
system/config/config.ini Normal file
View file

@ -0,0 +1,24 @@
// Yellow CMS configuration
// All directories and locations have to end with a slash
sitename = Website
author = Website
language = en
parser = markdown
template = default
stylesLocation = /media/styles/
imagesLocation = /media/images/
pluginsLocation = /media/plugins/
systemDir = system/
configDir = system/config/
pluginDir = system/plugins/
snippetDir = system/snippets/
templateDir = system/templates/
contentDir = content/
contentHomeDir = 1-home/
contentDefaultFile = page
contentExtension = .txt
configExtension = .ini
systemExtension = .php

View file

@ -0,0 +1,4 @@
---
Title: File not found
---
The requested file was not found. Oh no...

732
system/core/core.php Executable file
View file

@ -0,0 +1,732 @@
<?php
// Copyright (c) 2013 Datenstrom, http://www.datenstrom.se
// This file may be used and distributed under the terms of the public license.
// Yellow main class
class Yellow
{
const Version = "0.0.0"; //Hello world!
var $page; //current page data
var $pages; //current page tree, top level
var $toolbox; //toolbox with helpers
var $config; //site configuration
var $plugins; //site plugins
function __construct()
{
$this->toolbox = new Yellow_Toolbox();
$this->config = new Yellow_Config();
$this->config->setDefault("sitename", "Yellow");
$this->config->setDefault("author", "Yellow");
$this->config->setDefault("language", "en");
$this->config->setDefault("parser", "markdown");
$this->config->setDefault("template", "default");
$this->config->setDefault("baseLocation", $this->toolbox->getBaseLocation());
$this->config->setDefault("stylesLocation", "/media/styles/");
$this->config->setDefault("imagesLocation", "/media/images/");
$this->config->setDefault("pluginsLocation", "media/plugins/");
$this->config->setDefault("systemDir", "system/");
$this->config->setDefault("configDir", "system/config/");
$this->config->setDefault("pluginDir", "system/plugins/");
$this->config->setDefault("snippetDir", "system/snippets/");
$this->config->setDefault("templateDir", "system/templates/");
$this->config->setDefault("contentDir", "content/");
$this->config->setDefault("contentHomeDir", "1-home/");
$this->config->setDefault("contentDefaultFile", "page");
$this->config->setDefault("contentExtension", ".txt");
$this->config->setDefault("configExtension", ".ini");
$this->config->setDefault("systemExtension", ".php");
$this->config->setDefault("configFile", "config.ini");
$this->config->setDefault("yellowVersion", Yellow::Version);
$this->config->load($this->config->get("configDir").$this->config->get("configFile"));
$this->plugins = new Yellow_Plugins();
}
// Start CMS and handle request
function request()
{
$this->toolbox->timerStart($time);
$this->plugins->load();
$this->processRequest();
$this->toolbox->timerStop($time);
if(defined("DEBUG") && DEBUG>=1) echo "Yellow::request time:$time ms<br>\n";
}
// Process request
function processRequest()
{
$statusCode = 0;
$baseLocation = $this->config->get("baseLocation");
$location = $this->getRelativeLocation($baseLocation);
$fileName = $this->getContentFileName($location);
foreach($this->plugins->plugins as $key=>$value)
{
if(method_exists($value["obj"], "onRequest"))
{
$statusCode = $value["obj"]->onRequest($baseLocation, $location, $fileName);
if($statusCode) break;
}
}
if($statusCode == 0) $statusCode = $this->processRequestFile($baseLocation, $location, $fileName, $statusCode);
if(defined("DEBUG") && DEBUG>=1) echo "Yellow::processRequest status:$statusCode, location:$location<br>\n";
}
// Process request for a file
function processRequestFile($baseLocation, $location, $fileName, $statusCode, $cache = true)
{
if($statusCode == 0)
{
if(is_readable($fileName))
{
$time = gmdate("D, d M Y H:i:s", filemtime($fileName))." GMT";
if(isset($_SERVER["HTTP_IF_MODIFIED_SINCE"]) && $_SERVER["HTTP_IF_MODIFIED_SINCE"]==$time && $cache)
{
$statusCode = 304;
$this->sendStatus($statusCode);
} else {
$statusCode = 200;
header("Content-Type: text/html; charset=UTF-8");
if($cache)
{
header("Last-Modified: ".$time);
} else {
header("Cache-Control: no-cache");
header("Pragma: no-cache");
header("Expires: 0");
}
$fileHandle = @fopen($fileName, "r");
if($fileHandle)
{
$fileData = fread($fileHandle, filesize($fileName));
fclose($fileHandle);
} else {
die("Server problem: Can't read file '$fileName'!");
}
}
} else {
if($this->toolbox->isFileLocation($location) && is_dir($this->getContentDirectory("$location/")))
{
$statusCode = 301;
$this->sendStatus($statusCode, "Location: http://$_SERVER[SERVER_NAME]$baseLocation$location/");
} else {
$statusCode = 404;
}
}
}
if($statusCode >= 400)
{
header($this->toolbox->getHttpStatusFormated($statusCode));
header("Content-Type: text/html; charset=UTF-8");
$fileName = $this->config->get("configDir").sprintf("error%d.txt", $statusCode);
$fileHandle = @fopen($fileName, "r");
if($fileHandle)
{
$fileData = fread($fileHandle, filesize($fileName));
fclose($fileHandle);
} else {
die("Configuration problem: Can't open file '$fileName'!");
}
}
if($fileData != "") $this->sendPage($baseLocation, $location, $fileName, $fileData, $statusCode);
if(defined("DEBUG") && DEBUG>=1) echo "Yellow::processRequestFile base:$baseLocation, file:$fileName<br>\n";
return $statusCode;
}
// Send status response
function sendStatus($statusCode, $text = "")
{
header($this->toolbox->getHttpStatusFormated($statusCode));
if($text != "") header($text);
}
// Send page response
function sendPage($baseLocation, $location, $fileName, $fileData, $statusCode)
{
$this->pages = new Yellow_Pages($baseLocation, $this->toolbox, $this->config);
$this->page = new Yellow_Page($baseLocation, $location, $fileName, $fileData, $this->toolbox, $this->config);
$text = $this->page->getContentRawText();
foreach($this->plugins->plugins as $key=>$value)
{
if(method_exists($value["obj"], "onParseBefore"))
{
$text = $value["obj"]->onParseBefore($text, $statusCode);
}
}
if(is_null($this->plugins->plugins[$this->page->get("parser")])) die("Parser '".$this->page->get("parser")."' does not exist!");
$this->page->parser = $this->plugins->plugins[$this->page->get("parser")]["obj"];
$text = $this->page->parser->parse($text);
foreach($this->plugins->plugins as $key=>$value)
{
if(method_exists($value["obj"], "onParseAfter"))
{
$text = $value["obj"]->onParseAfter($text, $statusCode);
}
}
$this->page->setContent($text);
if(!$this->page->isExisting("description"))
{
$this->page->set("description", $this->toolbox->createTextDescription($this->page->getContent(), 150));
}
if(!$this->page->isExisting("keywords"))
{
$this->page->set("keywords", $this->toolbox->createTextKeywords($this->page->get("title"), 10));
}
$fileName = $this->config->get("templateDir").$this->page->get("template").$this->config->get("systemExtension");
if(!is_file($fileName)) die("Template '".$this->page->get("template")."' does not exist!");
global $yellow;
require($fileName);
}
// Execute a template snippet
function snippet($snippet)
{
$fileName = $this->config->get("snippetDir").$snippet.$this->config->get("systemExtension");
if(!is_file($fileName)) die("Snippet '$snippet' does not exist!");
global $yellow;
require($fileName);
}
// Return extra HTML header lines generated from plugins
function getHeaderExtra()
{
$header = "";
foreach($this->plugins->plugins as $key=>$value)
{
if(method_exists($value["obj"], "onHeaderExtra")) $header .= $value["obj"]->onHeaderExtra();
}
return $header;
}
// Return content location for current HTTP request, without base location
function getRelativeLocation($baseLocation)
{
$location = $this->toolbox->getRequestLocation();
$location = $this->toolbox->normaliseLocation($location);
$position = strlen($baseLocation);
return substr($location, $position);
}
// Return content file name from location
function getContentFileName($location)
{
return $this->toolbox->findFileFromLocation($location,
$this->config->get("contentDir"), $this->config->get("contentHomeDir"),
$this->config->get("contentDefaultFile"), $this->config->get("contentExtension"));
}
// Return content directory from location
function getContentDirectory($location)
{
return $this->toolbox->findFileFromLocation($location,
$this->config->get("contentDir"), $this->config->get("contentHomeDir"), "", "");
}
// Register plugin
function registerPlugin($name, $class, $version)
{
$this->plugins->register($name, $class, $version);
}
}
// Yellow page data
class Yellow_Page
{
var $baseLocation; //base location
var $location; //page location
var $fileName; //content file name
var $parser; //content parser
var $metaData; //meta data of page
var $rawData; //raw data of page (unparsed)
var $rawTextPos; //raw text of page (unparsed)
var $active; //page is active?
function __construct($baseLocation, $location, $fileName, $rawData, $toolbox, $config)
{
$this->baseLocation = $baseLocation;
$this->location = $location;
$this->fileName = $fileName;
$this->setRawData($rawData, $toolbox, $config);
$this->active = $toolbox->isActiveLocation($baseLocation, $location);
}
// Set page raw data
function setRawData($rawData, $toolbox, $config)
{
$this->metaData = array();
$this->rawData = $rawData;
$this->rawTextPos = 0;
$this->set("title", $toolbox->createTextTitle($this->location));
$this->set("author", $config->get("author"));
$this->set("language", $config->get("language"));
$this->set("parser", $config->get("parser"));
$this->set("template", $config->get("template"));
if(preg_match("/^(\-\-\-[\r\n]+)(.+?)([\r\n]+\-\-\-[\r\n]+)/s", $rawData, $parsed))
{
$this->rawTextPos = strlen($parsed[1]) + strlen($parsed[2]) + strlen($parsed[3]);
preg_match_all("/([^\:\r\n]+)\s*\:\s*([^\r\n]+)/s", $parsed[2], $matches, PREG_SET_ORDER);
foreach($matches as $match)
{
$this->set(strtolower($match[1]), $match[2]);
}
} else if(preg_match("/^([^\r\n]+)([\r\n]+=+[\r\n]+)/", $rawData, $parsed)) {
$this->rawTextPos = strlen($parsed[1]) + strlen($parsed[2]);
$this->set("title", $parsed[1]);
}
}
// Set page meta data
function set($key, $value)
{
$this->metaData[$key] = $value;
}
// Return page meta data
function get($key)
{
return is_null($this->metaData[$key]) ? "" : $this->metaData[$key];
}
// Return page meta data, HTML encoded
function getHtml($key)
{
return htmlspecialchars($this->get($key));
}
// Return page title, HTML encoded
function getTitle()
{
return $this->getHtml("title");
}
// Set page content, HTML encoded
function setContent($html)
{
$this->parser->html = $html;
}
// Return page content, HTML encoded
function getContent()
{
return $this->parser->html;
}
// Return page content, raw text
function getContentRawText()
{
return substr($this->rawData, $this->rawTextPos);
}
// Return absolut page location
function getLocation()
{
return $this->baseLocation.$this->location;
}
// Check if meta data exists
function isExisting($key)
{
return !is_null($this->metaData[$key]);
}
// Check if page is active
function isActive()
{
return $this->active;
}
}
// Yellow page tree from file system
class Yellow_Pages
{
var $pages; //scanned pages
function __construct($baseLocation, $toolbox, $config)
{
$this->scan($baseLocation, $toolbox, $config);
}
// Scan top-level pages
function scan($baseLocation, $toolbox, $config)
{
$this->pages = array();
foreach($toolbox->getDirectoryEntries($config->get("contentDir"), "/^[\d\-\.]+(.*)$/", true) as $entry)
{
$fileName = $config->get("contentDir").$entry."/".$config->get("contentDefaultFile").$config->get("contentExtension");
$location = $toolbox->findLocationFromFile($fileName, $config->get("contentDir"), $config->get("contentHomeDir"),
$config->get("contentDefaultFile"), $config->get("contentExtension"));
$fileHandle = @fopen($fileName, "r");
if($fileHandle)
{
$fileData = fread($fileHandle, 4096);
fclose($fileHandle);
} else {
$fileData = "";
}
$page = new Yellow_Page($baseLocation, $location, $fileName, $fileData, $toolbox, $config);
array_push($this->pages, $page);
}
}
// Return top-level pages
function root()
{
return $this->pages;
}
}
// Yellow toolbox with helpers
class Yellow_Toolbox
{
// Return location from current HTTP request
static function getRequestLocation()
{
$uri = $_SERVER["REQUEST_URI"];
return ($pos = strpos($uri, '?')) ? substr($uri, 0, $pos) : $uri;
}
// Return arguments from current HTTP request
static function getRequestLocationArguments()
{
$uri = $_SERVER["REQUEST_URI"];
return ($pos = strpos($uri, '?')) ? substr($uri, $pos+1) : "";
}
// Return base location
static function getBaseLocation()
{
$baseLocation = "/";
if(preg_match("/^(.*)\//", $_SERVER["SCRIPT_NAME"], $matches)) $baseLocation = $matches[1];
return $baseLocation;
}
// Normalise location and remove incorrect path tokens
static function normaliseLocation($location)
{
$str = str_replace('\\', '/', rawurldecode($location));
$location = ($str[0]=='/') ? '' : '/';
for($pos=0; $pos<strlen($str); ++$pos)
{
if($str[$pos] == '/')
{
if($str[$pos+1] == '/') continue;
if($str[$pos+1] == '.')
{
$posNew = $pos+1; while($str[$posNew] == '.') ++$posNew;
if($str[$posNew]=='/' || $str[$posNew]=='')
{
$pos = $posNew-1;
continue;
}
}
}
$location .= $str[$pos];
}
return $location;
}
// Check if location is specifying file or directory
static function isFileLocation($location)
{
return substr($location,-1,1) != "/";
}
// Check if location is within current HTTP request
static function isActiveLocation($baseLocation, $location)
{
$currentLocation = substr(self::getRequestLocation(), strlen($baseLocation));
if($location != "/")
{
$active = substr($currentLocation, 0, strlen($location))==$location;
} else {
$active = $currentLocation==$location;
}
return $active;
}
// Find file path from location
static function findFileFromLocation($location, $pathBase, $pathHome, $fileDefault, $fileExtension)
{
$path = $pathBase;
if($location != "/")
{
$tokens = explode('/', $location);
for($i=1; $i<count($tokens)-1; ++$i)
{
$entries = self::getDirectoryEntries($path, "/^[\d\-\.]+".$tokens[$i]."$/");
if(!empty($entries)) $tokens[$i] = $entries[0];
$path .= "$tokens[$i]/";
}
if($tokens[$i] != "")
{
$path .= $tokens[$i].$fileExtension;
} else {
$path .= $fileDefault.$fileExtension;
}
} else {
$path .= $pathHome.$fileDefault.$fileExtension;
}
return $path;
}
// Find location from file path
static function findLocationFromFile($fileName, $pathBase, $pathHome, $fileDefault, $fileExtension)
{
$location = "/";
if(substr($fileName, 0, strlen($pathBase)) == $pathBase) $fileName = substr($fileName, strlen($pathBase));
if(substr($fileName, 0, strlen($pathHome)) != $pathHome)
{
$tokens = explode('/', $fileName);
for($i=0; $i<count($tokens)-1; ++$i)
{
if(preg_match("/^[\d\-\.]+(.*)$/", $tokens[$i], $matches)) $tokens[$i] = $matches[1];
$location .= "$tokens[$i]/";
}
if($tokens[$i] != $fileDefault.$fileExtension)
{
$location .= substr($tokens[$i], 0, -strlen($fileExtension)-1);
}
} else {
if($fileName != $pathHome.$fileDefault.$fileExtension)
{
$location .= substr($fileName, $pathHome, -strlen($fileExtension)-1);
}
}
return $location;
}
// Return human readable HTTP server status
static function getHttpStatusFormated($statusCode)
{
switch($statusCode)
{
case 301: $text = "$_SERVER[SERVER_PROTOCOL] 301 Moved permanently"; break;
case 302: $text = "$_SERVER[SERVER_PROTOCOL] 302 Moved temporarily"; break;
case 304: $text = "$_SERVER[SERVER_PROTOCOL] 304 Not modified"; break;
case 404: $text = "$_SERVER[SERVER_PROTOCOL] 404 Not found"; break;
case 424: $text = "$_SERVER[SERVER_PROTOCOL] 424 Does not exist"; break;
default: die("Unknown HTTP status $statusCode!");
}
return $text;
}
// Return files and directories
static function getDirectoryEntries($path, $regex = ".*", $sort = false, $directories = true)
{
$entries = array();
$dirHandle = @opendir($path);
if($dirHandle)
{
while(($entry = readdir($dirHandle)) !== false)
{
if(substr($entry, 0, 1) == ".") continue;
if(preg_match($regex, $entry))
{
if($directories)
{
if(is_dir("$path/$entry")) array_push($entries, $entry);
} else {
if(is_file("$path/$entry")) array_push($entries, $entry);
}
}
}
if($sort) natsort($entries);
closedir($dirHandle);
}
return $entries;
}
// Create description from text
static function createTextDescription($text, $lengthMax)
{
$description = "";
preg_match_all("/\<p\>(.+?\<\/p\>)/s", $text, $parsedDescription, PREG_SET_ORDER);
foreach($parsedDescription as $matches)
{
preg_match_all("/([^\<]*)[^\>]+./s", $matches[1], $parsedUndoTag, PREG_SET_ORDER);
if(count($parsedUndoTag) > 0)
{
if(!empty($description)) $description .= " ";
foreach($parsedUndoTag as $matchTag)
{
$description .= preg_replace("/[\\x00-\\x1f]+/s", " ", $matchTag[1]);
}
}
if(strlen($description) > $lengthMax)
{
$description = substr($description, 0, $lengthMax-3)."...";
break;
}
}
return $description;
}
// Create keywords from text string
static function createTextKeywords($text, $keywordsMax)
{
$tokens = preg_split("/[,\s\(\)]/", strtolower($text));
foreach($tokens as $key => $value) if(strlen($value) < 3) unset($tokens[$key]);
return implode(", ", array_slice(array_unique($tokens), 0, $keywordsMax));
}
// Create title from text string
static function createTextTitle($text)
{
if(preg_match("/^.*\/(\w*)/", $text, $matches)) $text = ucfirst($matches[1]);
return $text;
}
// Detect PNG and JPG image dimensions
static function detectImageDimensions($fileName)
{
$width = $height = 0;
$fileHandle = @fopen($fileName, "rb");
if($fileHandle)
{
if(substr($fileName, -3) == "png")
{
$dataSignature = fread($fileHandle, 8);
$dataHeader = fread($fileHandle, 25);
if(!feof($fileHandle) && $dataSignature=="\x89PNG\r\n\x1a\n")
{
$width = (ord($dataHeader[10])<<8) + ord($dataHeader[11]);
$height = (ord($dataHeader[14])<<8) + ord($dataHeader[15]);
}
} else if(substr($fileName, -3) == "jpg") {
$dataSignature = fread($fileHandle, 11);
$dataHeader = fread($fileHandle, 147);
$dataHeader = fread($fileHandle, 16);
if(!feof($fileHandle) && $dataSignature=="\xff\xd8\xff\xe0\x00\x10JFIF\0")
{
$width = (ord($dataHeader[7])<<8) + ord($dataHeader[8]);
$height = (ord($dataHeader[5])<<8) + ord($dataHeader[6]);
}
}
fclose($fileHandle);
}
return array($width, $height);
}
// Start timer
static function timerStart(&$time)
{
$time = microtime(true);
}
// Stop timer and calcuate elapsed time (milliseconds)
static function timerStop(&$time)
{
$time = intval((microtime(true)-$time) * 1000);
}
}
// Yellow configuration
class Yellow_Config
{
var $config; //configuration
var $configDefaults; //configuration defaults
function __construct()
{
$this->config = array();
$this->configDefaults = array();
}
// Load configuration from file
function load($fileName)
{
$fileData = @file($fileName);
if($fileData)
{
foreach($fileData as $line)
{
if(preg_match("/^\//", $line)) continue;
preg_match("/^\s*(.*?)\s*=\s*(.*?)\s*$/", $line, $matches);
if($matches[1]!="" && $matches[2]!="")
{
$this->set($matches[1], $matches[2]);
if(defined("DEBUG") && DEBUG>=3) echo "Yellow_Config::load key:$matches[1] $matches[2]<br/>\n";
}
}
}
}
// Set default configuration
function setDefault($key, $value)
{
$this->configDefaults[$key] = $value;
}
// Set configuration
function set($key, $value)
{
$this->config[$key] = $value;
}
// Return configuration
function get($key)
{
return is_null($this->config[$key]) ? $this->configDefaults[$key] : $this->config[$key];
}
// Return configuration, HTML encoded
function getHtml($key)
{
return htmlspecialchars($this->get($key));
}
// Check if configuration exists
function isExisting($key)
{
return !is_null($this->config[$key]);
}
}
// Yellow plugins
class Yellow_Plugins
{
var $plugins; //registered plugins
function __construct()
{
$this->plugins = array();
}
// Load plugins
function load()
{
global $yellow;
require_once("core_markdown.php");
require_once("core_rawhtml.php");
foreach($yellow->toolbox->getDirectoryEntries($yellow->config->get("pluginDir")) as $entry)
{
$fileName = "$entry/plugin_$entry.php";
if(is_file($fileName)) require_once($fileName);
}
foreach($this->plugins as $key=>$value)
{
$this->plugins[$key]["obj"] = new $value["class"];
if(defined("DEBUG") && DEBUG>=2) echo "Yellow_Plugins::load class:$value[class] $value[version]<br/>\n";
if(method_exists($this->plugins[$key]["obj"], "initPlugin"))
{
$this->plugins[$key]["obj"]->initPlugin($yellow);
}
}
}
// Register plugin
function register($name, $class, $version)
{
if(is_null($this->plugins[$name]))
{
$this->plugins[$name] = array();
$this->plugins[$name]["class"] = $class;
$this->plugins[$name]["version"] = $version;
}
}
}
?>

55
system/core/core_markdown.php Executable file
View file

@ -0,0 +1,55 @@
<?php
// Copyright (c) 2013 Datenstrom, http://www.datenstrom.se
// This file may be used and distributed under the terms of the public license.
// Markdown parser core plugin
class Yellow_Markdown
{
var $markdown; //markdown parser
var $html; //generated HTML
// Initialise plugin
function initPlugin($yellow)
{
$this->markdown = new Yellow_MarkdownExtraParser($yellow);
}
// Parse text
function parse($text)
{
return $this->html = $this->markdown->transform($text);
}
}
require("markdown.php");
class Yellow_MarkdownExtraParser extends MarkdownExtra_Parser
{
var $yellow; //access to API
function __construct($yellow)
{
$this->yellow = $yellow;
parent::__construct();
}
// Handle images
function _doImages_inline_callback($matches)
{
$path = $matches[3]=="" ? $matches[4] : $matches[3];
$src = $this->yellow->config->get("baseLocation").$this->yellow->config->get("imagesLocation").$path;
list($width, $height) = $this->yellow->toolbox->detectImageDimensions(".".$this->yellow->config->get("imagesLocation").$path);
$alt = $matches[2];
$title =& $matches[7];
$result = "<img src=\"".$this->encodeAttribute($src)."\"";
if($width && $height) $result .= " width=\"$width\" height=\"$height\"";
if(isset($alt)) $result .= " alt=\"".$this->encodeAttribute($alt)."\"";
if(isset($title)) $result .= " title=\"".$this->encodeAttribute($title)."\"";
$result .= $this->empty_element_suffix;
return $this->hashPart($result);
}
}
$yellow->registerPlugin("markdown", "Yellow_Markdown", "0.1.0");
?>

18
system/core/core_rawhtml.php Executable file
View file

@ -0,0 +1,18 @@
<?php
// Copyright (c) 2013 Datenstrom, http://www.datenstrom.se
// This file may be used and distributed under the terms of the public license.
// Raw HTML parser core plugin
class Yellow_RawHtml
{
var $html; //generated HTML
// Parse text, dummy transformation
function parse($text)
{
return $this->html = $text;
}
}
$yellow->registerPlugin("rawhtml", "Yellow_RawHtml", "0.1.0");
?>

3050
system/core/markdown.php Executable file

File diff suppressed because it is too large Load diff

3
system/snippets/footer.php Executable file
View file

@ -0,0 +1,3 @@
<div class="footer">&copy; 2013 <?php echo $yellow->config->getHtml("sitename") ?></div>
</body>
</html>

14
system/snippets/header.php Executable file
View file

@ -0,0 +1,14 @@
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml" lang="<?php echo $yellow->page->getHtml("language") ?>">
<head>
<meta charset="utf-8" />
<meta name="description" content="<?php echo $yellow->page->getHtml("description") ?>" />
<meta name="keywords" content="<?php echo $yellow->page->getHtml("keywords") ?>" />
<meta name="author" content="<?php echo $yellow->page->getHtml("author") ?>" />
<title><?php echo $yellow->config->getHtml("sitename")." - ".$yellow->page->getHtml("title") ?></title>
<link rel="shortcut icon" href="<?php echo $yellow->config->get("baseLocation").$yellow->config->get("imagesLocation")."default_icon.png" ?>" />
<link href="<?php echo $yellow->config->get("baseLocation").$yellow->config->get("stylesLocation")."default_style.css" ?>" rel="styleSheet" media="all" type="text/css" />
<link href="<?php echo $yellow->config->get("baseLocation").$yellow->config->get("stylesLocation")."print_style.css" ?>" rel="styleSheet" media="print" type="text/css" />
<?php echo $yellow->getHeaderExtra() ?>
</head>
<body>
<div class="header"><a href="<?php echo $yellow->config->get("baseLocation")."/" ?>"><?php echo $yellow->config->getHtml("sitename") ?></a></div>

7
system/snippets/navigation.php Executable file
View file

@ -0,0 +1,7 @@
<div class="navigation">
<ul>
<?php foreach($yellow->pages->root() as $page): ?>
<li><a<?php echo $page->isActive() ? " class=\"active\"" : "" ?> href="<?php echo $page->getLocation() ?>"><?php echo $page->getTitle() ?></a></li>
<?php endforeach ?>
</ul>
</div>

7
system/templates/default.php Executable file
View file

@ -0,0 +1,7 @@
<?php $yellow->snippet("header") ?>
<?php $yellow->snippet("navigation") ?>
<div class="content">
<h1><?php echo $yellow->page->getTitle() ?></h1>
<?php echo $yellow->page->getContent() ?>
</div>
<?php $yellow->snippet("footer") ?>