last updating on api controller dispatching

This commit is contained in:
Erik Amaru Ortiz
2013-08-30 11:31:59 -04:00
parent b5af0e0e4a
commit 324e0f6320
27 changed files with 1165 additions and 32 deletions

View File

@@ -6,6 +6,8 @@
"license": "GNU Affero General Public License version 3",
"require": {
"luracast/restler" : "v3.0.0"
"luracast/restler" : "dev-master",
"bshaffer/oauth2-server-php": "v1.0",
"twig/twig": "v1.13.2"
}
}

View File

@@ -1038,54 +1038,62 @@ class Bootstrap
}
//use Luracast\Restler\Format\XmlFormat as XmlFormat;
/**
* This method dispatch rest/api services
* it implement "Restler" library
* This method dispatch rest/api service
*
* @param $url string Contains the url request
* @author Erik Amaru Ortiz <aortiz.erik@gmail.com>
* @author Erik Amaru Ortiz <erik@colosa.com>
* @param $uri
* @param $config
* @param string $apiClassesPath
* @internal param string $url Contains the url request
*/
public function dispatchApiService($uri, $config, $apiClassesPath = '')
{
$rest = new Luracast\Restler\Restler();
$rest->setAPIVersion('1.0');
$dataUri = explode('/', $uri);
array_shift($dataUri);
$reqClass = ucfirst(array_shift($dataUri));
$servicesDir = PATH_CORE . 'services' . PATH_SEP;
$apiDir = $servicesDir . 'api' . PATH_SEP;
$namespace = 'Services_Api_';
$classFile = $apiDir . $namespace . $reqClass . '.php';
$classDir = $apiDir . 'processmaker' . PATH_SEP;
$rest->setSupportedFormats('JsonFormat', 'XmlFormat');
$rest = new Luracast\Restler\Restler();
$rest->setAPIVersion('1.0');
$rest->setSupportedFormats('JsonFormat', 'XmlFormat');//, 'HtmlFormat');
//$rest->setOverridingFormats('UploadFormat', 'JsonFormat', 'XmlFormat', 'HtmlFormat');
$_SERVER['REQUEST_URI'] = $uri;
$classFile = $classDir . 'Services_Api_ProcessMaker_' . $reqClass . '.php';
$classFile2 = $classDir . DIRECTORY_SEPARATOR . $reqClass . '.php';
if (file_exists($classFile)) {
require_once $classFile;
$_SERVER['REQUEST_URI'] = $uri;
$rest->addAPIClass($namespace . $reqClass);
$rest->addAPIClass('Services_Api_ProcessMaker_' . $reqClass);
} elseif (file_exists($classFile2)) {
require_once $classFile2;
$rest->addAPIClass("\\Services\\Api\\Processmaker\\" . $reqClass);
} else {
$rest->handleError(500);
}
//Luracast\Restler\Format\HtmlFormat::$viewPath = $apiDir . 'oauth2/views';
//require_once $apiDir . 'oauth2/Server.php';
//$rest->addAuthenticationClass('Api\\OAuth2\\Server', '');
$rest->handle();
die;
// OLD CODE FROM HERE
///
// OLD CODE FROM HERE, we can get some interisting things there on the future
//
$rest->setSupportedFormats('JsonFormat', 'XmlFormat');
// getting all services class

View File

@@ -65,13 +65,21 @@
</head>
<body>
<div id="content" class="exceptionreset">
<h1>ProcessMaker, looks like something went wrong.</h1>
<div class="block_exception clear_fix"><h2>
<abbr title="RuntimeException">{$exceptionClass}</abbr>: {$title}</h2>
<h1>{$title}</h1>
<div class="block_exception clear_fix">
<h2>
<abbr title="RuntimeException">{$exceptionClass}</abbr>: {$message}
</h2>
</div>
<div class="block">
<ol class="traces list_exception">
{$message}
{foreach from=$trace item=line}
{if $line.class}
<li>At <b>{$line.class}{$line.type}</b><i>{$line.function}()</i><br/>in {$line.file} line {$line.line}</li>
{else}
<li>At {$line.function}() in {$line.file} line {$line.line}</li>
{/if}
{/foreach}
</ol>
</div>
</div>

View File

@@ -0,0 +1,25 @@
<?php
namespace Services\Api\ProcessMaker;
class Application
{
public function get($id)
{
$data = array(
"APP_UID" => $id,
"PRO_UID" => "13885168416038181883131343548151",
"DUMMY" => "sample data"
);
return $data;
}
public function post($requestData = null)
{
$requestData;
$requestData['processed'] = true;
return $requestData;
}
}

View File

@@ -7,15 +7,20 @@
* To change this template use File | Settings | File Templates.
*/
class Services_Api_Say
class Services_Api_ProcessMaker_Trigger
{
public function hello($to='world')
{
return array('success'=>true, "message"=>"Hello $to!");
}
public function hi($to, $name)
public function hi($name)
{
return "Hi $to -> $name";
return "Hi $name";
}
protected function secret()
{
return 'S E C R E T';
}
}

View File

@@ -0,0 +1,121 @@
<?php
namespace Api\OAuth2;
use Luracast\Restler\iAuthenticate;
use OAuth2_Request;
use OAuth2_Response;
use OAuth2_GrantType_AuthorizationCode;
use OAuth2_Storage_Pdo;
use OAuth2_Server;
/**
* Class Server
*
* @package OAuth2
*
*/
class Server implements iAuthenticate
{
/**
* @var OAuth2_Server
*/
protected static $server;
/**
* @var OAuth2_Storage_Pdo
*/
protected static $storage;
/**
* @var OAuth2_Request
*/
protected static $request;
public function __construct()
{
$dir = __DIR__ . '/db/';
$file = 'oauth.sqlite';
if (!file_exists($dir . $file)) {
include_once $dir . 'rebuild_db.php';
}
static::$storage = new \OAuth2\Storage\Pdo(
array('dsn' => 'sqlite:' . $dir . $file)
);
static::$request = \OAuth2\Request::createFromGlobals();
static::$server = new \OAuth2\Server(static::$storage);
static::$server->addGrantType(
new \OAuth2\GrantType\AuthorizationCode(static::$storage)
);
}
/**
* Stage 1: Client sends the user to this page
*
* User responds by accepting or denying
*
* @view oauth2/server/authorize.twig
* @format HtmlFormat
*/
public function authorize()
{
static::$server->getResponse(static::$request);
return array('queryString' => $_SERVER['QUERY_STRING']);
}
/**
* Stage 2: User response is captured here
*
* Success or failure is communicated back to the Client using the redirect
* url provided by the client
*
* On success authorization code is sent along
*
*
* @param bool $authorize
*
* @format JsonFormat,UploadFormat
*/
public function postAuthorize($authorize = false)
{
$response = static::$server->handleAuthorizeRequest(
static::$request,
(bool)$authorize
);
die($response->send());
}
/**
* Stage 3: Client directly calls this api to exchange access token
*
* It can then use this access token to make calls to protected api
*
* @format JsonFormat,UploadFormat
*/
public function postGrant()
{
$response = static::$server->handleGrantRequest(
static::$request
);
die($response->send());
}
/**
* Sample api protected with OAuth2
*
* For testing the oAuth token
*
* @access protected
*/
public function access()
{
return array(
'friends' => array('john', 'matt', 'jane')
);
}
/**
* Access verification method.
*
* API access will be denied when this method returns false
*
* @return boolean true when api access is allowed; false otherwise
*/
public function __isAllowed()
{
return self::$server->verifyResourceRequest(static::$request);
//return self::$server->verifyAccessRequest(static::$request);
}
}

Binary file not shown.

View File

@@ -0,0 +1,32 @@
<?php
// determine where the sqlite DB will go
$dbfile = __DIR__.'/oauth.sqlite';
// remove sqlite file if it exists
if (file_exists($dbfile)) {
unlink($dbfile);
}
if (!is_writable(__DIR__)) {
// try to set permissions.
if (!@chmod(__DIR__, 0777)) {
throw new Exception("Unable to write to $dbfile");
}
}
// rebuild the DB
$db = new PDO(sprintf('sqlite://%s', $dbfile));
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->exec('CREATE TABLE oauth_clients (client_id TEXT, client_secret TEXT, redirect_uri TEXT)');
$db->exec('CREATE TABLE oauth_access_tokens (access_token TEXT, client_id TEXT, user_id TEXT, expires TIMESTAMP, scope TEXT)');
$db->exec('CREATE TABLE oauth_authorization_codes (authorization_code TEXT, client_id TEXT, user_id TEXT, redirect_uri TEXT, expires TIMESTAMP, scope TEXT)');
$db->exec('CREATE TABLE oauth_refresh_tokens (refresh_token TEXT, client_id TEXT, user_id TEXT, expires TIMESTAMP, scope TEXT)');
// add test data
$db->exec('INSERT INTO oauth_clients (client_id, client_secret) VALUES ("demoapp", "demopass")');
chmod($dbfile, 0777);
// $db->exec('INSERT INTO oauth_access_tokens (access_token, client_id) VALUES ("testtoken", "Some Client")');
// $db->exec('INSERT INTO oauth_authorization_codes (authorization_code, client_id) VALUES ("testcode", "Some Client")');

View File

@@ -0,0 +1,4 @@
# views
### home for the restler view files
When HtmlFormat is used, it looks into this folder for view (template) files

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,158 @@
<?php
use Luracast\Restler\Restler;
use Luracast\Restler\Util;
$call_trace = '';
function exceptions()
{
global $call_trace;
$r = Util::$restler;
$source = $r->_exceptions;
if (count($source)) {
$source = end($source);
$traces = array();
do {
$traces += $source->getTrace();
} while ($source = $source->getPrevious());
$traces += debug_backtrace();
$call_trace
= parse_backtrace($traces, 0);
} else {
$call_trace
= parse_backtrace(debug_backtrace());
}
}
exceptions();
function parse_backtrace($raw, $skip = 1)
{
$output = "";
foreach ($raw as $entry) {
if ($skip-- > 0) {
continue;
}
//$output .= print_r($entry, true) . "\n";
$output .= "\nFile: " . $entry['file'] . " (Line: " . $entry['line'] . ")\n";
if (isset($entry['class']))
$output .= $entry['class'] . "::";
$output .= $entry['function']
. "( " . json_encode($entry['args']) . " )\n";
}
return $output;
}
//print_r(get_defined_vars());
//print_r($response);
$icon;
if ($success && isset($api)) {
$arguments = implode(', ', $api->parameters);
$icon = "<icon class=\"success\"></icon>";
$title = "{$api->className}::"
. "{$api->methodName}({$arguments})";
} else {
if (isset($response['error']['message'])) {
$icon = '<icon class="denied"></icon>';
$title = end(explode(':',$response['error']['message']));
} else {
$icon = '<icon class="warning"></icon>';
$title = 'No Matching Resource';
}
}
function render($data, $shadow=true)
{
$r = '';
if (empty($data))
return $r;
$r .= $shadow ? "<ul class=\"shadow\">\n": "<ul>\n";
if (is_array($data)) {
// field name
foreach ($data as $key => $value) {
$r .= '<li>';
$r .= is_numeric($key)
? "[<strong>$key</strong>] "
: "<strong>$key: </strong>";
$r .= '<span>';
if (is_array($value)) {
// recursive
$r .= render($value,false);
} else {
// value, with hyperlinked hyperlinks
if (is_bool($value)) {
$value = $value ? 'true' : 'false';
}
$value = htmlentities($value, ENT_COMPAT, 'UTF-8');
if (strpos($value, 'http://') === 0) {
$r .= '<a href="' . $value . '">' . $value . '</a>';
} else {
$r .= $value;
}
}
$r .= "</span></li>\n";
}
} elseif (is_bool($data)) {
$r .= '<li>' . ($data ? 'true' : 'false') . '</li>';
} else {
$r .= "<li><strong>$data</strong></li>";
}
$r .= "</ul>\n";
return $r;
}
$reqHeadersArr = array();
$requestHeaders = $_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI'] . ' ' . $_SERVER['SERVER_PROTOCOL'] . PHP_EOL;
foreach ($reqHeadersArr as $key => $value) {
if ($key == 'Host')
continue;
$requestHeaders .= "$key: $value" . PHP_EOL;
}
// $requestHeaders = $this->encode(apache_request_headers(), FALSE,
// FALSE);
$responseHeaders = implode(PHP_EOL, headers_list()).PHP_EOL.'Status: HTTP/1.1 ';
$responseHeaders .= Util::$restler->responseCode.' '.\Luracast\Restler\RestException::$codes[Util::$restler->responseCode];
?>
<!DOCTYPE html>
<html>
<head>
<title><?php echo $title?></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<style>
<?php include __DIR__.'/debug.css'; ?>
</style>
</head>
<body>
<div id="breadcrumbs-one">
<?php
if(Util::$restler->exception){
$stages = Util::$restler->exception->getStages();
$curStage = Util::$restler->exception->getStage();
foreach($stages['success'] as $stage){
echo "<a href=\"#\">$stage</a>";
}
foreach($stages['failure'] as $stage){
echo '<a href="#" class="failure">'
. $stage
. ($stage==$curStage ? ' <span class="state"/> ' : '')
. '</a>';
}
} else {
foreach(Util::$restler->_events as $stage){
echo "<a href=\"#\">$stage</a>";
}
}
?>
</div>
<header>
<h1><?php echo $title ?></h1>
</header>
<article>
<h2>Response:<right><?php echo $icon;?></right></h2>
<pre class="header"><?php echo $responseHeaders ?></pre>
<?php echo render($response); ?>
<p>Restler v<?php echo Restler::VERSION?></p>
</article>
</body>
</html>

View File

@@ -0,0 +1,15 @@
{% if googleAnalyticsCode is defined %}
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', '{{ googleAnalyticsCode }}']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
{% endif %}

View File

@@ -0,0 +1,61 @@
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="{{ basePath }}/css/demo.css">
<link rel="stylesheet" href="{{ basePath }}/css/shared.css">
</head>
<body>
<!--[if lt IE 7]>
<p class="chromeframe">You are using an outdated browser. <a href="http://browsehappy.com/">Upgrade your browser today</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to better experience this site.</p>
<![endif]-->
{% include 'oauth2/analytics.twig' %}
{% include 'oauth2/github.twig' %}
<div id="container">
<header role="banner">
{% block header %}
<hgroup>
<h1>Restler 3</h1>
<h2>OAuth 2 Demo App</h2>
</hgroup>
<nav class="primary">
<ul class="menu">
<li class="current">
<a href="http://luracast.com">Home</a>
</li>
<li>
<a href="../">More</a>
</li>
<li>
<a href="http://github.com/Luracast">Source</a>
</li>
<li>
<a href="http://twitter.com/Luracast">Twitter</a>
</li>
<li>
<a href="http://github.com/bshaffer">OAuth2</a>
</li>
</ul>
</nav>
{% endblock %}
</header>
<article class="home" role="main">
<div role="main">
{% block content %}
{% endblock %}
</div>
</article>
</div>
</body>
</html>

View File

@@ -0,0 +1,21 @@
{% extends "oauth2/client/base.twig" %}
{% block content %}
<h3>Authorization Failed!</h3>
<p>
It seems authorization has been denied for the following reasons:
</p>
<ul>
<li>
{% if response.error.error_description %}
{{ response.error.error_description }}
{# optional "error_uri" param #}
{% if response.error_uri %}
(<a href="{{ response.error.error_uri }}">more information</a>)
{% endif %}
{% else %}
<em>authorization server did not supply an error message</em>
{% endif %}
</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,12 @@
{% extends "oauth2/client/base.twig" %}
{% block content %}
<h3>Authorization Error</h3>
<p>
{{ response.error.error_description }}
{% if response.error.error_uri is defined %}
(<a href="{{response.error.error_uri}}">more information</a>)
{% endif %}
</p>
<a href="{{ basePath }}">back</a>
{% endblock %}

View File

@@ -0,0 +1,15 @@
{% extends "oauth2/client/base.twig" %}
{% block content %}
<h3>Authorization Granted!</h3>
<pre><code> Access Token: {{ response.token }} </code></pre>
<p>
Here are your friends:
</p>
<ul>
{% for friend in response.friends %}
<li>{{ friend }}</li>
{% endfor %}
</ul>
<div class="help"><em>The API call can be seen at <a href="{{ response.endpoint }}" target="_blank">{{ response.endpoint }}</a></em></div>
{% endblock %}

View File

@@ -0,0 +1,13 @@
{% extends "oauth2/client/base.twig" %}
{% block content %}
<h3>Demo App</h3>
<p>
We would like to use your information in order to integrate with your friends,
use your personal information for nefarious purposes, and to make your life better somehow.
</p>
<p>
Click below to integrate with that service you belong to:
</p>
<a class="button" href="{{ response.authorize_url }}?response_type=code&client_id=demoapp&redirect_uri={{ response.authorize_redirect_url|url_encode() }}">Authorize</a>
{% endblock %}

View File

@@ -0,0 +1 @@
<a href="https://github.com/Luracast/Restler"><img style="position: absolute; top: 0; right: 0; border: 0;z-index:100000" src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub"></a>

View File

@@ -0,0 +1,36 @@
{% extends "oauth2/server/base.twig" %}
{% block content %}
<p>
<strong>Demo App</strong> would like to access the following data:
</p>
<ul>
<li>friends</li>
<li>memories</li>
<li>hopes, dreams, passions, etc.</li>
<li>sock drawer</li>
</ul>
<p>It will use this data to:</p>
<ul>
<li>integrate with friends</li>
<li>make your life better</li>
<li>miscellaneous nefarious purposes</li>
</ul>
<ul class="authorize_options">
<li>
<form action="{{ 'authorize' ~ '?' ~ response.queryString }}" method="post">
<input type="submit" class="button authorize"
value="Yes, I Authorize This Request"/>
<input type="hidden" name="authorize" value="1"/>
</form>
</li>
<li class="cancel">
<form id="cancel" action="{{ 'authorize' ~ '?' ~ response.queryString }}"
method="post">
<a href="#"
onclick="document.getElementById('cancel').submit()">cancel</a>
<input type="hidden" name="authorize" value="0"/>
</form>
</li>
</ul>
{% endblock %}

View File

@@ -0,0 +1,34 @@
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="{{ basePath }}/css/lockdin.css">
<link rel="stylesheet" href="{{ basePath }}/css/shared.css">
</head>
<body>
<!--[if lt IE 7]>
<p class="chromeframe">You are using an outdated browser. <a href="http://browsehappy.com/">Upgrade your browser today</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to better experience this site.</p>
<![endif]-->
{% include 'oauth2/analytics.twig' %}
{% include 'oauth2/github.twig' %}
{% include 'oauth2/server/header.html' %}
<div id="container">
<article class="home" role="main">
<div id="content" role="main">
{% block content %}
{% endblock %}
</div>
</article>
</div>
</body>
</html>

View File

@@ -0,0 +1,52 @@
<div id="header" class="global-nav member">
<div class="top-nav">
<div class="wrapper">
<ul class="util" role="navigation">
<li class="tab username-cont">
<a href="#" class="tab-name username">You <span class="menu-indicator"></span></a>
</li>
</ul>
<h2 class="logo"><a href="#" title="Home">Lock'd <span>in</span></a></h2>
<div class="account">
<span>You'll never get your data back</span>
</div>
</div>
</div>
<div class="bottom-nav">
<div class="wrapper">
</ul>
</li>
<ul class="nav" role="navigation">
<li id="nav-primary-home" class="tab selected"><a href="#" class="tab-name"><span>Home</span></a></li>
<li id="nav-primary-profile" class="tab"><a href="#" class="tab-name"><span>Profile</span></a></li>
<li id="nav-primary-contacts" class="tab "><a href="/#" class="tab-name"><span>Contacts</span></a></li>
<li id="nav-primary-groups" class="tab "><a href="#" class="tab-name"><span>Groups</span></a></li>
<li id="nav-primary-jobs" class="tab "><a href="#" class="tab-name"><span>Jobs</span></a></li>
<li id="nav-primary-inbox-links" class="tab "><a href="#" class="tab-name"><span>Inbox</span></a></li>
<li id="nav-primary-company" class="tab"><a href="#" class="tab-name"><span>Companies</span></a></li>
<li id="nav-primary-news" class="tab"><a href="#" class="tab-name"><span>News</span></a></li>
<li id="nav-primary-more" class="tab "><a href="#" class="tab-name"><span>More</span></a></li>
</ul>
<form id="global-search" role="search" action="/search/fpsearch" method="get" accept-charset="UTF-8" name="commonSearch" class="global-search ">
<fieldset>
<div class="search-scope styled-dropdown" id="yui-gen1"><span class="label"> <span> People </span> </span></div>
<span class="search-box-container">
<span id="search-autocomplete-container" title="Tip: You can also search by keyword, company, school..." class="/typeahead">
<label for="main-search-box" class="ghost" id="yui-gen2" style="display: none; ">Search...</label>
<input name="keywords" id="main-search-box" class="search-term yui-ac-input" type="text" value="" autocomplete="off" placeholder="Search...">
<span id="search-typeahead-container"></span>
</span>
<input name="search" value="Search" class="search-go" type="submit">
</span>
</fieldset>
<a id="search-link" class="search-link" href="/search?trk=advsrch">Advanced</a>
</form>
</div>
</div>
</div>

View File

@@ -0,0 +1,2 @@
<?php
echo $basePath;

View File

@@ -0,0 +1 @@
Showing {{basePath}}

View File

@@ -0,0 +1 @@
Showing "{{ basePath }}"

View File

@@ -0,0 +1,56 @@
<?php return <<<TEMPLATE
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<base href="{$basePath}/"/>
<title>{$title}</title>
<!-- Including the jQuery UI Human Theme -->
<link rel="stylesheet"
href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.0/themes/humanity/jquery-ui.css"
type="text/css" media="all"/>
<!-- Our own stylesheet -->
<link rel="stylesheet" type="text/css" href="styles.css"/>
</head>
<body>
<h1>{$title}</h1>
<h2>
<a href="../">Go
Back to the Examples &raquo;</a></h2>
<div id="main">
<ul class="todoList">
{$_('include','todo/list.php','response')}
</ul>
<a id="addButton" class="green-button" href="#">Add a Task</a>
</div>
<!-- This div is used as the base for the confirmation jQuery UI POPUP. Hidden by CSS. -->
<div id="dialog-confirm" title="Delete TODO Item?">Are you sure you want to
delete this task?
</div>
<p class="note">{$description}</p>
<!-- Including our scripts -->
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.0/jquery-ui.min.js"></script>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
TEMPLATE;

View File

@@ -0,0 +1,12 @@
<?php return <<<TEMPLATE
<li id="todo-{$id}" class="todo">
<div class="text">{$text}</div>
<div class="actions">
<a href="#" class="edit">Edit</a>
<a href="#" class="delete">Delete</a>
</div>
</li>
TEMPLATE;

View File

@@ -1026,9 +1026,11 @@ try {
}
}
} catch (Exception $e) {
//g::pr($e->getTrace()); die;
Bootstrap::renderTemplate('error.tpl', array(
'title' => 'ProcessMaker Bootstrap Exception',
'message' => nl2br($e->getMessage()),
'exceptionClass' => get_class($e)
'exceptionClass' => get_class($e),
'trace' => $e->getTrace()
));
}