Commit dc0dfc5b authored by Martyn Smith's avatar Martyn Smith Committed by Martyn Smith
Browse files
parents 63a935a6 b2945c5a
<?php
/**
* This program is part of Mahara
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* @package mahara
* @subpackage core
* @author Penny Leach <penny@catalyst.net.nz>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL
* @copyright (C) 2006,2007 Catalyst IT Ltd http://catalyst.net.nz
*
*/
define('INTERNAL', 1);
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
json_headers();
$markasread = param_integer('markasread', 0);
if ($markasread) {
db_begin();
try {
foreach ($_GET as $k => $v) {
if (preg_match('/^unread\-(\d+)$/',$k,$m)) {
set_field('notification_internal_activity', 'read', 1, 'id', $m[1]);
}
}
}
catch (Exception $e) {
db_rollback();
$data = array('error' => $e->getMessage);
echo json_encode($data);
}
db_commit();
$data = array('success' => 1);
echo json_encode($data);
exit;
}
// normal processing
$type = param_alpha('type', 'all');
$limit = param_integer('limit', 10);
$offset = param_integer('offset', 0);
$userid = $SESSION->get('id');
if ($type == 'all') {
$count = count_records('notification_internal_activity', 'usr', $userid);
$records = get_rows('notification_internal_activity', 'usr', $userid,
'ctime DESC', '*', $offset, $limit);
} else {
$count = count_records_select('notification_internal_activity', 'usr = ? AND type = ?',
array($userid,$type));
$records = get_rows_select('notification_internal_activity', 'usr = ? AND type = ?',
array($userid, $type),
'ctime DESC', '*', $offset, $limit);
}
if (empty($records)) {
$records = array();
}
$data = array();
$star = theme_get_image_path('star.png');
$unread = get_string('unread', 'activity');
foreach ($records as $r) {
$r['date'] = format_date(strtotime($r['ctime']));
}
$activity = array(
'count' => $count,
'offset' => $offset,
'limit' => $limit,
'data' => $records,
'star' => $star,
'unread' => $unread,
);
echo json_encode($activity);
?>
......@@ -30,8 +30,92 @@ define('SUBMENUITEM', 'activity');
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
$smarty = smarty();
$types = get_records('activity_type', 'admin', 0);
$smarty->display('account/activity/index.tpl');
$readsavefail = get_string('failedtomarkasread', 'activity');
$readsave = get_string('markedasread', 'activity');
$javascript = <<<JAVASCRIPT
var activitylist = new TableRenderer(
'activitylist',
'index.json.php',
[
function(r) {
if (r.url) {
return TD(null,A({'href': r.url}, r.message));
}
return TD(null,r.message);
},
'ctime',
function (r, d) {
if (r.read == 0) {
return TD(null,IMG({'src' : d.star, 'alt' : d.unread}));
}
return TD(null);
},
function (r) {
if (r.read == 0) {
return TD(null, INPUT({'type' : 'checkbox', 'class' : 'tocheck', 'name' : 'unread-' + r.id}));
}
return TD(null);
}
]
);
activitylist.type = 'all';
activitylist.statevars.push('type');
activitylist.updateOnLoad();
function checkall(c) {
var e = getElementsByTagAndClassName(null,c);
if (e) {
for (cb in e) {
log(e[cb]);
e[cb].checked = 'checked';
}
}
return false;
}
function markread(form) {
var c = 'tocheck';
var e = getElementsByTagAndClassName(null,'tocheck',form);
var pd = {};
for (cb in e) {
if (e[cb].checked == true) {
pd[e[cb].name] = 1;
}
}
pd['markasread'] = 1;
var d = loadJSONDoc('index.json.php', pd);
d.addCallbacks(function (data) {
if (data.success) {
$('messagediv').innerHTML = '$readsave';
activitylist.doupdate();
}
if (data.error) {
$('messagediv').innerHTML = '$readsavefail(' + data.error + ')';
}
},
function () {
$('messagediv').innerHTML = '$readsavefail';
activitylist.doupdate();
}
)
}
JAVASCRIPT;
$smarty = smarty(array('tablerenderer'));
$smarty->assign('site_menu', site_menu());
$smarty->assign('selectall', 'checkall(\'tocheck\'); return false;');
$smarty->assign('markread', 'markread(this); return false;');
$smarty->assign('typechange', 'activitylist.doupdate({\'type\':this.options[this.selectedIndex].value});');
$smarty->assign('types', $types);
$smarty->assign('INLINEJAVASCRIPT', $javascript);
$smarty->display('account/activity/index.tpl');
?>
......@@ -38,28 +38,26 @@ foreach ($sitepages as $page) {
asort($pageoptions);
$f = array(
'name' => 'editsitepage',
'method' => 'post',
'ajaxpost' => true,
'name' => 'editsitepage',
'method' => 'post',
'ajaxpost' => true,
'ajaxsuccessfunction' => 'contentSaved',
'ajaxformhandler' => 'savesitepage.json.php',
'action' => '',
'elements' => array(
'action' => '',
'elements' => array(
'pagename' => array(
'type' => 'select',
'title' => get_string('pagename'),
'value' => 'home',
'type' => 'select',
'title' => get_string('pagename'),
'value' => 'home',
'options' => $pageoptions
),
'pagetext' => array(
'name' => 'pagetext',
'type' => 'wysiwyg',
'rows' => 20,
'cols' => 80,
'title' => get_string('pagetext'),
'name' => 'pagetext',
'type' => 'wysiwyg',
'rows' => 20,
'cols' => 80,
'title' => get_string('pagetext'),
'description' => get_string('pagecontents'),
'value' => '',
'rules' => array(
'rules' => array(
'required' => true
)
),
......@@ -69,8 +67,30 @@ $f = array(
),
)
);
$form = form($f);
function editsitepage_submit($values) {
global $USER;
$data = new StdClass;
$data->name = $values['pagename'];
$data->content = $values['pagetext'];
$data->mtime = db_format_timestamp(time());
$data->mauthor = $USER->id;
try {
update_record('site_content', $data, 'name');
$result['error'] = false;
$result['message'] = get_string('savedsuccessfully');
}
catch (SQLException $e) {
$result['error'] = 'local';
$result['message'] = get_string('savefailed');
}
json_headers();
echo json_encode($result);
exit;
}
$js = array();
if (use_html_editor()) {
array_unshift($js,'tinymce');
......@@ -138,7 +158,7 @@ EOJS;
$jsstrings = array('discardpageedits');
$smarty = smarty($js,array(),$jsstrings);
$smarty = smarty($js, array(), $jsstrings);
$smarty->assign('pageeditform', $form);
$smarty->assign('INLINEJAVASCRIPT', $ijs);
$smarty->display('admin/editsitepage.tpl');
......
debugObject = function (obj) {
// gives a nice, stable string representation for objects,
// ignoring any methods
var keyValuePairs = [];
for (var k in obj) {
var v = obj[k];
if (typeof(v) != 'function') {
keyValuePairs.push([k, v]);
}
};
keyValuePairs.sort(compare);
log( "{" + map(
function (pair) {
return map(repr, pair).join(":");
},
keyValuePairs
).join(", ") + "}");
};
......@@ -39,4 +39,17 @@ $string['typevirusrelease'] = 'Virus flag release';
$string['type'] = 'Activity type: ';
$string['attime'] = 'at';
$string['prefsdescr'] = 'For options other than Activity log, notifications will still go into the Activity log, but will be automatically marked as read';
$string['date'] = 'Date';
$string['read'] = 'Read';
$string['unread'] = 'Unread';
$string['markasread'] = 'Mark as read';
$string['selectall'] = 'Select all';
$string['alltypes'] = 'All types';
$string['markedasread'] = 'Marked your notifications as read';
$string['failedtomarkasread'] = 'Failed to mark your notifications as read';
?>
......@@ -172,4 +172,5 @@ $string['activity'] = 'Recent activity';
$string['emailname'] = 'Mahara System'; // robot!
$string['save'] = 'Save';
$string['update'] = 'Update';
?>
......@@ -130,15 +130,12 @@ function count_records($table, $field1=null, $value1=null, $field2=null, $value2
* @return int The count of records returned from the specified criteria.
* @throws SQLException
*/
// NOTE: commented out until required
/*
function count_records_select($table, $select='', $values=null, $countitem='COUNT(*)') {
if ($select) {
$select = 'WHERE ' . $select;
}
return count_records_sql('SELECT '. $countitem .' FROM '. get_config('dbprefix') . $table . ' ' . $select, $values);
}
*/
/**
* Get the result of a SQL SELECT COUNT(...) query.
......@@ -153,13 +150,10 @@ function count_records_select($table, $select='', $values=null, $countitem='COUN
* @return int The count.
* @throws SQLException
*/
// NOTE: commented out until required
/*
function count_records_sql($sql, $values=null) {
$rs = get_recordset_sql($sql, $values);
return reset($rs->fields);
}
*/
/// GENERIC FUNCTIONS TO GET, INSERT, OR UPDATE DATA ///////////////////////////////////
......@@ -344,7 +338,7 @@ function get_recordset_sql($sql, $values=null, $limitfrom=null, $limitnum=null)
///Special case, 0 must be -1 for ADOdb
$limitfrom = empty($limitfrom) ? -1 : $limitfrom;
$limitnum = empty($limitnum) ? -1 : $limitnum;
$rs = $db->SelectLimit($sql, $limitnum, $limitfrom,$values);
$rs = $db->SelectLimit($sql, $limitnum, $limitfrom, $values);
} else {
$rs = false;
if (!empty($values) && is_array($values) && count($values) > 0) {
......
......@@ -143,7 +143,7 @@ class Form {
*
* @var string
*/
private $onsubmit = '';
//private $onsubmit = '';
/**
* Whether to submit the form via ajax
......@@ -159,12 +159,19 @@ class Form {
*/
private $ajaxsuccessfunction = '';
/**
* Name of a javascript function to call on failed ajax submission
*
* @var string
*/
private $ajaxfailurefunction = '';
/**
* Name of a php script to handle an ajax-submitted form
*
* @var string
*/
private $ajaxformhandler = '';
//private $ajaxformhandler = '';
/**
* The tab index for this particular form.
......@@ -248,8 +255,8 @@ class Form {
'action' => '',
'onsubmit' => '',
'ajaxpost' => false,
'ajaxformhandler' => '',
'ajaxsuccessfunction' => '',
'ajaxfailurefunction' => '',
'autofocus' => false,
'submit' => true,
'elements' => array()
......@@ -268,12 +275,9 @@ class Form {
$this->autofocus = $data['autofocus'];
if ($data['ajaxpost']) {
$this->ajaxformhandler = $data['ajaxformhandler'];
$this->ajaxpost = $data['ajaxpost'] && !empty($this->ajaxformhandler);
$this->ajaxpost = true;
$this->ajaxsuccessfunction = $data['ajaxsuccessfunction'];
if ($this->ajaxpost) {
$this->onsubmit = 'return ' . $this->name . '_submit();';
}
$this->ajaxfailurefunction = $data['ajaxfailurefunction'];
}
if (isset($data['renderer'])) {
......@@ -394,6 +398,7 @@ class Form {
if (!isset($element['goto'])) {
throw new FormException('Cancel element "' . $element['name'] . '" has no page to go to');
}
// @todo what happens in the case of ajax post?
redirect($element['goto']);
return;
}
......@@ -417,6 +422,7 @@ class Form {
// Call the user defined function for processing a submit
// This function should really redirect/exit after it has
// finished processing the form.
// @todo maybe it should do just that...
$function($values);
}
else {
......@@ -428,6 +434,17 @@ class Form {
if ($this->autofocus !== false) {
$this->auto_focus_first_error();
}
// If the form has been submitted by ajax, return ajax
if ($this->ajaxpost) {
$errors = $this->get_errors();
$json = array();
foreach ($errors as $element) {
$json[$element['name']] = $element['error'];
}
echo json_encode(array('error' => 'local', 'message' => '@todo allow forms to specify a local error message', 'errors' => $json));
exit;
}
}
}
......@@ -479,13 +496,16 @@ class Form {
*/
public function build() {
$result = '<form';
foreach (array('name', 'method', 'action', 'onsubmit') as $attribute) {
foreach (array('name', 'method', 'action') as $attribute) {
$result .= ' ' . $attribute . '="' . $this->{$attribute} . '"';
}
$result .= ' id="' . $this->name . '"';
if ($this->fileupload) {
$result .= ' enctype="multipart/form-data"';
}
if ($this->ajaxpost) {
$result .= ' onsubmit="return ' . $this->name . '_submit();"';
}
$result .= ">\n";
// @todo masks attempts in form_render_element, including the error handling there
......@@ -526,7 +546,7 @@ class Form {
if ($this->ajaxpost) {
$result .= '<script language="javascript" type="text/javascript">';
$result .= $this->validate_js();
//$result .= $this->validate_js();
$result .= $this->submit_js();
$result .= "</script>\n";
}
......@@ -620,17 +640,10 @@ class Form {
$result = array();
$global = ($this->method == 'get') ? $_GET : $_POST;
foreach ($this->get_elements() as $element) {
//if (isset($global[$element['name']])) {
// $result[$element['name']] = $global[$element['name']];
//}
//else if ($element['type'] == 'file' && isset($_FILES[$element['name']])) {
// $result[$element['name']] = $_FILES[$element['name']];
//}
//else {
// $result[$element['name']] = null;
//}
$result[$element['name']] = $this->get_value($element);
}
log_debug($result);
log_debug($_POST);
return $result;
}
......@@ -670,94 +683,98 @@ class Form {
}
/**
* Returns a js function to perform simple validation based off
* the definition array.
* Returns a js function to submit an ajax form
* Expects formname_message() to be defined by the renderer,
* and formname_validate() to be defined.
*/
private function validate_js() {
$result = 'function ' . $this->name . "_validate(){\nvar ok=true;\n";
foreach ($this->get_elements() as $element) {
if (isset($element['rules']) && is_array($element['rules'])) {
foreach ($element['rules'] as $rule => $data) {
// Get the rule
$function = 'form_rule_' . $rule . '_js';
if (!function_exists($function)) {
@include_once('form/rules/' . $rule . '.php');
if (!function_exists($function)) {
continue;
}
}
$rdata = $function($element['name']);
$errmsgid = $element['name'] . '_msg';
$result .= 'if (!(' . $rdata->condition . ")){" ;
$result .= $this->name . '_set_error(\'' . $errmsgid . '\',\''
. $rdata->message . "');ok=false;}\n";
$result .= 'else{' . $this->name . '_rem_error(\'' . $errmsgid . "');}\n";
}
}
if ($element['type'] == 'submit' || $element['type'] == 'submitcancel') {
$submitname = $element['name'];
}
private function submit_js() {
$result = <<<EOF
function {$this->name}_submit() {
// eventually we should check input types for wysiwyg before doing this
// Also should only save wysiwyg elements in the form, not all of them...
if (typeof(tinyMCE) != 'undefined') { tinyMCE.triggerSave(); }
processingStart();
var data = {};
EOF;
foreach ($this->get_elements() as $element) {
$result .= " data['" . $element['name'] . "'] = $('" . $element['name'] . "').value;\n";
if (!empty($element['ajaxmessages'])) {
$messageelement = $element['name'];
}
$result .= "return ok;\n}\n";
$js_messages_function = 'form_renderer_' . $this->renderer . '_messages_js';
if (!function_exists($js_messages_function)) {
@include_once('form/renderers/' . $this->renderer . '.php');
if (!function_exists($js_messages_function)) {
throw new FormException('No renderer message function "' . $js_messages_function . '"');
}
$result .= " data['form_{$this->name}'] = '';\n";
if (!isset($messageelement)) {
throw new FormException('At least one submit-type element is required for AJAX forms');
}
$action = ($this->action) ? $this->action : 'editsitepage.php';
$result .= <<<EOF
// This does a post. Gets are much simpler in mochikit and we
// could check whether there are any big fields (like wysiwyg,
// textarea) and do a get (doSimpleXmlHttpRequest) instead if
// there aren't any.
var req = getXMLHttpRequest();
req.open('POST','{$action}');
req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
var d = sendXMLHttpRequest(req,queryString(data));
d.addCallbacks(
function (result) {
var data = evalJSONRequest(result);
debugObject(data);
if (data.error) {
{$this->name}_message(data.message);
for (error in data.errors) {
{$this->name}_set_error(error + '_msg', data.errors[error]);
}
EOF;
if (!empty($this->ajaxfailurefunction)) {
$result .= " {$this->ajaxfailurefunction}();\n";
}
$result .= <<<EOF
}
if (!isset($submitname)) {
throw new FormException('Submit element required for js messages');
}
return $result . $js_messages_function($this->name,$submitname);
//return $result;
else {
{$this->name}_message(data.message, 'ok');
EOF;
if (!empty($this->ajaxsuccessfunction)) {
$result .= " {$this->ajaxsuccessfunction}();\n";
}
/**
* Returns a js function to submit an ajax form
* Expects formname_message() to be defined by the renderer,
* and formname_validate() to be defined.
*/
private function submit_js() {
$result = 'function ' . $this->name . "_submit(){\n";
// eventually we should check input types for wysiwyg before doing this:
$result .= "if (typeof(tinyMCE) != 'undefined') { tinyMCE.triggerSave(); }\n";
$result .= 'if (!' . $this->name . "_validate()) { return false; }\n";
$result .= 'processingStart();';
$result .= "var data = {};\n";
foreach ($this->get_elements() as $element) {
$result .= "data['" . $element['name'] . "'] = $('" . $element['name'] . "').value;\n";
}
// This does a post. Gets are much simpler in mochikit and we
// could check whether there are any big fields (like wysiwyg,
// textarea) and do a get (doSimpleXmlHttpRequest) instead if
// there aren't any.
$result .= 'var req = getXMLHttpRequest();';
$result .= "req.open('POST','" . $this->ajaxformhandler . "');\n";
$result .= "req.setRequestHeader('Content-type','application/x-www-form-urlencoded');\n";
$result .= "var d = sendXMLHttpRequest(req,queryString(data));\n";
$result .= 'd.addCallback(function (result) {';
$result .= 'var data = evalJSONRequest(result);';