Skip to content

Instantly share code, notes, and snippets.

@betaman
Created June 9, 2013 19:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save betaman/5744783 to your computer and use it in GitHub Desktop.
Save betaman/5744783 to your computer and use it in GitHub Desktop.
Elefant CMS JSON App: Retrieve Data as JSON For Singlepage Websites
<?php
class Json extends \Restful {
// Accessible via:
// `GET /json/api/run/layout/index`
// retrieves controller run data from page and all includes in a layout template
// `GET /json/api/run/page/index`
// retrieves controller run data from page
// `GET /json/api/run/blocks/index?id=sidebar-testpage'
// retrieves controller run data from handler
// TODO get data of db table
// `GET /json/api/data/layout/index`
// retrieves data from page and all includes in a layout template
// `GET /json/api/data/page/index`
// retrieves data from page
// `GET /json/api/data/blocks/index?id=sidebar-testpage'
// retrieves data from handler
public function get_run(){
// get arguments and params
$params = func_get_args ();
$data = $_GET;
$this->wrap = true;
$handler = $params[0];
// return page or page and all includes of the layout
if ($handler === "page" || $handler === "layout") {
// get pageId
$id = $params[1];
if ($id) {
$page = $this->get_rendered_page ($id);
if ($handler === "layout") {
$page->includes = $this->get_includes($page->layout, $id);
}
return $page;
}
}
// return the include
else {
return $this->get_include();
}
}
private function get_template_file ($template) {
$tpl = new Template();
// Resolve the template to a file name, in one of:
// `apps/appname/views/filename.html`
// `layouts/themename/filename.html`
// `layouts/filename.html`
// `layouts/filename/filename.html`
// `layouts/default.html`
if (strstr ($template, '/')) {
list ($app, $view) = preg_split ('/\//', $template, 2);
$file = sprintf ($tpl->view_folders, $app, $view . '.' . $tpl->file_extension);
if (! file_exists ($file)) {
$file = $tpl->layouts_folder . '/' . $app . '/' . $view . '.' . $tpl->file_extension;
if (! file_exists ($file)) {
throw new RuntimeException ('Template not found: ' . $template);
}
}
} elseif (file_exists ($tpl->layouts_folder . '/' . $template . '.' . $tpl->file_extension)) {
$file = $tpl->layouts_folder . '/' . $template . '.' . $tpl->file_extension;
} elseif (file_exists ($tpl->layouts_folder . '/' . $template . '/' . $template . '.' . $tpl->file_extension)) {
$file = $tpl->layouts_folder . '/' . $template . '/' . $template . '.' . $tpl->file_extension;
} else {
$file = $tpl->layouts_folder . '/' . $tpl->default_layout . '.' . $tpl->file_extension;
}
$out = file_get_contents ($file);
return $out;
// TODO caching
/*
// The cache file is named based on the original
$cache = $this->cache_folder . '/' . str_replace ('/', '-', $template) . '.php';
if (! file_exists ($cache) || filemtime ($file) > filemtime ($cache)) {
// Regenerate cached file
$out = file_get_contents ($file);
$out = $this->parse_template ($out);
if (! is_writeable (dirname ($cache))) {
die ('Cache folder must be writeable to continue. Please check the <a href="http://www.elefantcms.com/wiki/Installing-Elefant" target="_blank">installation instructions</a> and try again.');
}
if (! file_put_contents ($cache, $out)) {
throw new RuntimeException ('Failed to generate cached template: ' . $cache);
}
}
ob_start ();
require ($cache);
return ob_get_clean ();
*/
}
// returns an array with all includes used in the layout template
// (ie '/layouts/default.html' )
private function get_includes($layout, $id){
$val = $this->get_template_file($layout);
$tpl = new Template();
// remove spaces
$val = preg_replace ('/[\t\n ]+(\?|\&)/', '\1', trim ($val));
// normalize <span data-embed> tags to {! tags !}
$val = preg_replace ('/<[^>]*?data-embed="([^"]+)".*?>.*?<\/.*?>/', '{! \1 !}', $val);
$parts = preg_split ('/(\{\! ?.*? ?\!\})/e', $val, -1, PREG_SPLIT_DELIM_CAPTURE);
$out = '';
$includes = array();
foreach ($parts as $part) {
if (strpos ($part, '{! ') === 0) {
$part = trim ($part, '{! }');
$part = str_replace("[id]", $id, $part);
$include = array(handler=>$part, rendered=>$this->get_include($part));
array_push($includes, $include);
}
}
return $includes;
}
private function get_include($val="") {
// if no value is provided
// host, path and params are extracted from the URI
if($val === ""){
array_shift($this->controller->params);
$params = $this->controller->params;
$data = $_GET;
$url['host'] = '';
$url['path'] = implode("/", $params );
}
// if a value is provided
// host, path and params are extracted from the passed String
else {
$url = parse_url ($val);
if (! isset ($url['host'])) {
$url['host'] = '';
}
$params = explode("/", $url['path']);
if (isset ($url['query'])) {
parse_str (html_entity_decode ($url['query'], ENT_COMPAT, 'UTF-8'), $data);
} else {
$data = array ();
}
}
// run the controller to get the output
$out = $this->controller->run ($url['host'] . $url['path'], $data);
return $out;
}
private function get_rendered_page ($id) {
if (! User::require_admin ()) {
$page = Webpage::query ()
->where ('access', 'public')
->where ('id', $id)
->single ();
} else {
$page = Webpage::query ()
->where ('id', $id)
->single ();
}
if ($page) {
// convert it from a Webpage object into an ordinary object
$orig = $page->orig ();
// create the Output Object
$out = new stdClass();
$out->id = $id;
$out->title = $orig->title;
$out->menu_title = ($orig->menu_title === "") ? $out->title : $orig->menu_title;
$out->window_title = ($orig->window_title === "") ? $out->title : $orig->window_title;
$out->access = $orig->access;
$out->layout = $orig->layout;
$out->description = $orig->description;
$out->keywords = $orig->keywords;
// use Navigation to get the path
$n = new Navigation;
$out->path = $n->path ($id);
// run the controller to get the output
$controller = new Controller (conf ('Hooks'));
$tpl = new Template (conf ('General', 'charset'), $controller);
$out->body = $tpl->run_includes ($orig->body);
if (User::require_admin ()) {
// show admin edit buttons
if (User::is_valid () && User::is ('admin')) {
$lock = new Lock ('Webpage', $id);
$out->locked = $lock->exists ();
$out->body = $tpl->render ('admin/editable', $orig) . $out->body;
}
}
$out->body = str_replace("/json/api/page/", "/", $out->body);
}
// Return some data
return $out;
}
//TODO povide an Interface for PUT, POST and DELETE
// Accessible via `POST /myapp/api/article`
public function post_page () {
// Return an error
return $this->error ('Error message');
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment