Skip to content

Instantly share code, notes, and snippets.

@rc1
Last active December 17, 2015 02:18
Show Gist options
  • Select an option

  • Save rc1/5534265 to your computer and use it in GitHub Desktop.

Select an option

Save rc1/5534265 to your computer and use it in GitHub Desktop.
Snippets that demonstrate incorporating SymphonyCMS datasources with Express.js and Jade. There are million different way to do this. This assumes all the data of the datasource can be held in memory... objectively not a bad thing: free memcache. We have had SymphonyCMSs notify instances of Express.js when changes in the db have occurred. Howeve…
var http = require('http');
var xml2js = require('xml2js');
var xmlParser = new xml2js.Parser({
normalize: false
});
// SymphonyCMS
var SymphonyCMS = function (options){
options = options || {};
this.host = options.host;
this.path = options.path;
this.datasourcePrefix = (typeof options.datasourcePrefix !== "undefined") ? options.datasourcePrefix : '';
this.noop = function () {};
this.content = {};
// Middleware
this.hasFetchedInitalContent = false;
this.stillLoadingCallbacks = [];
};
// Holds all requests until the intial fetch has happened from symphony
// Then append a symphony data object to each request,
SymphonyCMS.prototype.middleware = function () {
var self = this;
return function (req, res, next) {
if (self.hasFetchedInitalContent) {
res.locals.symphony = self.data;
req.symphony = self.data;
next();
} else {
self.stillLoadingCallbacks.push(function () {
res.locals.symphony = self.data;
next();
});
}
};
};
// Fetches new data from the server
SymphonyCMS.prototype.fetch = function (callback) {
var self = this;
var options = {
host: this.host,
port: 80,
path: this.path,
method: 'GET'
};
var req = http.request(options, function(res) {
var data = '';
res.on('data', function(chunk){ data += chunk; });
res.on('end', function(){
xmlParser.parseString(data, function (err, data) {
if (err) {
callback(err);
return;
}
self.parse(data);
if (callback) {
self.hasFetchedInitalContent = true;
callback();
self.stillLoadingCallbacks.forEach(function (middlewareCallback) {
middlewareCallback();
});
self.stillLoadingCallbacks = [];
}
});
});
});
req.on('error', function(err) {
if (callback) { callback(err); }
});
req.end();
};
SymphonyCMS.prototype.parse = function (data) {
for(var key in data) {
if (key.indexOf(this.datasourcePrefix) === 0) {
this[key.replace(this.datasourcePrefix, "")] = data[key];
}
}
};
module.exports = SymphonyCMS;
var SymphonyCMS = require('./lib/SymphonyCMS');
// create a new Symphony
var symphonyCMS = new SymphonyCMS({
host : 'cms.website.com',
path : '/all/'
});
// load data from symphony 6 secs after the last successful responce (can be more, can be less, can be different in production & development mode)
function fetchDataSourceHandler(err) {
if (err) {
console.log(err);
}
setTimeout(function () {
symphonyCMS.fetch(fetchDataSourceHandler);
}, 6000);
}
fetchDataSourceHandler();
// server
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 8001);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
// add the symphony middleware
app.use(symphonyCMS.middleware());
app.use(app.router);
});
// render a jade page on a route
app.get("/", function (req, res) {
res.render("index", {
title: "hello"
});
});
// show the json provided from symphony
app.get("/json/", function (req, res) {
res.json(symphonyCMS.data);
});
// the middleware will expose a symphony object here
body
.container
- each entry in symphony.texts[0].entry
h1!= entry.title[0]._
p!= entry.text[0]._
footer
// and we can output to the console.
// this is by far the best advantage of
// express and jade.
// the following will not be sent to
// the client, but will appear in the
// console/terminal during development
// get for interogation of the data
// and debugging.
- console.log(symphony);
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
omit-xml-declaration="yes"
encoding="UTF-8"
indent="yes" />
<xsl:template match="/">
<xsl:copy-of select="*"/>
</xsl:template>
</xsl:stylesheet>
<!DOCTYPE data PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<data>
<params>
<today>2013-05-07</today>
<current-time>21:13</current-time>
<this-year>2013</this-year>
<this-month>05</this-month>
<this-day>07</this-day>
<timezone>+01:00</timezone>
<website-name>Symphony CMS</website-name>
<page-title>all</page-title>
<root>http://cms.website.com</root>
<workspace>http://cms.website.com/workspace</workspace>
<root-page>all</root-page>
<current-page>all</current-page>
<current-page-id>77</current-page-id>
<current-path>/all</current-path>
<parent-path>/</parent-path>
<current-query-string>?</current-query-string>
<current-url>http://cms.website.com/all</current-url>
<upload-limit>5242880</upload-limit>
<symphony-version>2.3.2</symphony-version>
<page-types>
<item handle="xml">XML</item>
</page-types>
<site-mode>live</site-mode>
</params>
<events></events>
<texts>
<section id="7" handle="texts">Texts</section>
<entry id="7">
<title handle="about-the-project">ABOUT THE PROJECT</title>
<order>1</order>
<text mode="unformatted">Some text</text>
</entry>
<entry id="8">
<title handle="title-1">TITLE 1</title>
<order>2</order>
<text mode="unformatted">Some text...</text>
</entry>
<entry id="10">
<title handle="title-2">TITLE 2</title>
<order>3</order>
<text mode="unformatted">Some more text...</text>
</entry>
<entry id="9">
<title handle="title-3">TITLE 3</title>
<order>4</order>
<text mode="unformatted">Even more text...</text>
</entry>
</texts>
</data>
{
"params": [
{
"today": [
"2013-05-07"
],
"current-time": [
"21:16"
],
"this-year": [
"2013"
],
"this-month": [
"05"
],
"this-day": [
"07"
],
"timezone": [
"+01:00"
],
"website-name": [
"Symphony CMS"
],
"page-title": [
"all"
],
"root": [
"http://content.o-o-o-o.co.uk"
],
"workspace": [
"http://content.o-o-o-o.co.uk/workspace"
],
"root-page": [
"all"
],
"current-page": [
"all"
],
"current-page-id": [
"77"
],
"current-path": [
"/all"
],
"parent-path": [
"/"
],
"current-query-string": [
"?"
],
"current-url": [
"http://content.o-o-o-o.co.uk/all"
],
"upload-limit": [
"5242880"
],
"symphony-version": [
"2.3.2"
],
"page-types": [
{
"item": [
{
"_": "XML",
"$": {
"handle": "xml"
}
}
]
}
],
"site-mode": [
"live"
]
}
],
"events": [
""
],
"texts": [
{
"section": [
{
"_": "Texts",
"$": {
"id": "7",
"handle": "texts"
}
}
],
"entry": [
{
"$": {
"id": "7"
},
"title": [
{
"_": "ABOUT THE PROJECT",
"$": {
"handle": "about-the-project"
}
}
],
"order": [
"1"
],
"text": [
{
"_": "Some text",
"$": {
"mode": "unformatted"
}
}
]
},
{
"$": {
"id": "8"
},
"title": [
{
"_": "TITLE 1",
"$": {
"handle": "title-1"
}
}
],
"order": [
"2"
],
"text": [
{
"_": "Some text...",
"$": {
"mode": "unformatted"
}
}
]
},
{
"$": {
"id": "10"
},
"title": [
{
"_": "TITLE 2",
"$": {
"handle": "title-2"
}
}
],
"order": [
"3"
],
"text": [
{
"_": "Some more text...",
"$": {
"mode": "unformatted"
}
}
]
},
{
"$": {
"id": "9"
},
"title": [
{
"_": "TITLE 3",
"$": {
"handle": "title-3"
}
}
],
"order": [
"4"
],
"text": [
{
"_": "Even more text...",
"$": {
"mode": "unformatted"
}
}
]
}
]
}
],
"upload": [
{
"section": [
{
"_": "Upload",
"$": {
"id": "8",
"handle": "upload"
}
}
],
"entry": [
{
"$": {
"id": "11"
},
"text": [
{
"_": "More text",
"$": {
"mode": "unformatted"
}
}
]
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment