Commit 6919fe38 authored by Nigel McNie's avatar Nigel McNie Committed by Nigel McNie
Browse files
parents b3ba1c90 edf6fc17
......@@ -31,7 +31,7 @@ define('SUBMENUITEM', 'sitemenu');
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
$strings = array('edit','delete','update','cancel','add','name','unknownerror');
$adminstrings = array('deletefailed','deletingmenuitem','savingmenuitem',
$adminstrings = array('confirmdeletemenuitem', 'deletefailed','deletingmenuitem','savingmenuitem',
'noadminfiles','loggedinmenu','loggedoutmenu','linkedto','externallink','adminfile',
'loadingmenuitems','menuitemsloaded','failedloadingadminfiles',
'failedloadingmenuitems');
......@@ -225,8 +225,9 @@ function edititem(item) {
// Receive standard json error message
// Request deletion of a menu item from the db
function delitem(itemid) {
logDebug({$getstring['deletingmenuitem']});
sendjsonrequest('deletemenuitem.json.php',{'itemid':itemid}, getitems);
if (confirm({$getstring['confirmdeletemenuitem']})) {
sendjsonrequest('deletemenuitem.json.php',{'itemid':itemid}, getitems);
}
}
// Send the menu item in the form to the database.
......
<?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 artefact-file
* @author Richard Mansfield <richard.mansfield@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');
$uploadnumber = param_integer('uploadnumber');
$createid = param_variable('createid');
safe_require('artefact', 'blog');
$path = ArtefactTypeBlogPost::get_temp_file_path($createid, $uploadnumber);
log_debug($path);
serve_file($path, '');
?>
......@@ -56,6 +56,7 @@ if (!$blogpost) {
$description = '';
$checked = '';
$pagetitle = 'newblogpost';
$focuselement = 'title';
}
else {
$blogpostobj = new ArtefactTypeBlogPost($blogpost);
......@@ -67,6 +68,7 @@ else {
$description = $blogpostobj->get('description');
$checked = !$blogpostobj->get('published');
$pagetitle = 'editblogpost';
$focuselement = 'description'; // Doesn't seem to work with tinyMCE.
}
......@@ -76,10 +78,11 @@ else {
* and cancel buttons are in their own form at the bottom of the page,
* with the file upload form appearing in between.
*/
$form = pieform(array(
$textinputform = pieform(array(
'name' => 'editpost',
'method' => 'post',
'action' => '',
'autofocus' => $focuselement,
'elements' => array(
'parent' => array(
'type' => 'hidden',
......@@ -109,12 +112,6 @@ $form = pieform(array(
),
'defaultvalue' => $description
),
'thisisdraft' => array(
'type' => 'checkbox',
'title' => get_string('thisisdraft', 'artefact.blog'),
'description' => get_string('thisisdraftdesc', 'artefact.blog'),
'defaultvalue' => $checked
),
)
));
......@@ -130,11 +127,31 @@ $getstring = quotestrings(array(
'myfiles',
),
'artefact.blog' => array(
'absolutemiddle',
'absolutebottom',
'alignment',
'attach',
'baseline',
'blogpost',
'border',
'bottom',
'browsemyfiles',
'cancel',
'dimensions',
'horizontalspace',
'insert',
'insertimage',
'left',
'middle',
'name',
'nofilesattachedtothispost',
'remove',
'right',
'texttop',
'top',
'update',
'verticalspace',
'noimageshavebeenattachedtothispost',
)));
......@@ -183,7 +200,8 @@ var attached = new TableRenderer(
'attachedfiles',
'attachedfiles.json.php',
[
function (r) { return TD(null, IMG({'src':config.themeurl + 'images/' + r.artefacttype + '.gif'})); },
function (r) { return TD(null, IMG({'src':config.themeurl + 'images/' + r.artefacttype + '.gif',
'alt':r.artefacttype})); },
'title',
'description',
function (r) {
......@@ -203,10 +221,14 @@ attached.updateOnLoad();
// Show/hide the 'no attachments' message if there are no/some attachments
function checknoattachments() {
function redrawAttachList() {
if (attached.tbody.hasChildNodes()) {
hideElement(attached.table.previousSibling);
showElement(attached.table);
// Make sure row classes alternate 'r1', 'r0', 'r1', etc.
for (var i = 0; i < attached.tbody.childNodes.length; i++) {
setElementClass(attached.tbody.childNodes[i], 'r'+(i+1)%2);
}
}
else {
showElement(attached.table.previousSibling);
......@@ -229,19 +251,20 @@ function attachtopost(data) {
appendChildNodes(attached.tbody,
TR({'id':rowid},
map(partial(TD,null),
[IMG({'src':config.themeurl+'images/'+data.artefacttype+'.gif'}),
[IMG({'src':config.themeurl+'images/'+data.artefacttype+'.gif',
'alt':data.artefacttype}),
data.title, data.description,
INPUT({'type':'button', 'class':'button',
'value':{$getstring['remove']},
'onclick':"removefrompost('"+rowid+"')"})])));
checknoattachments();
redrawAttachList();
}
// Remove a row from the attached files list.
function removefrompost(rowid) {
removeElement(rowid);
checknoattachments();
redrawAttachList();
}
......@@ -261,7 +284,7 @@ function fileattached_id(id) {
// Save the blog post.
function saveblogpost() {
var data = {'title' : $('editpost_title').value,
'draft' : $('editpost_thisisdraft').checked,
'draft' : $('draftpost_thisisdraft').checked,
'createid' : {$createid},
'blog' : {$blog},
'blogpost' : {$blogpost}};
......@@ -286,6 +309,7 @@ function saveblogpost() {
if (typeof(tinyMCE) != 'undefined') {
tinyMCE.triggerSave();
}
data.body = $('editpost_description').value;
sendjsonrequest('saveblogpost.json.php', data,
function () { window.location = '{$wwwroot}artefact/blog/view/?id={$blog}';});
......@@ -296,13 +320,300 @@ function canceledit() { // Uploaded files will deleted by cron cleanup.
window.location = '{$wwwroot}artefact/blog/view/?id={$blog}';
}
// Override the image button on the tinyMCE editor. Rather than the
// normal image popup, open up a form below the blogpost body form
// which allows the user to select an image from the list of image
// files attached to the post.
// The contents of this function is stolen straight out of the tinyMCE
// code in tinymce/themes/advanced/editor_template_src.js
function getSelectedImgAttributes (editorid) {
var src = "", alt = "", border = "", hspace = "", vspace = "", width = "", height = "", align = "";
var title = "", onmouseover = "", onmouseout = "", action = "insert";
var img = tinyMCE.imgElement;
var inst = tinyMCE.getInstanceById(editorid);
if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img") {
img = tinyMCE.selectedElement;
tinyMCE.imgElement = img;
}
if (img) {
// Is it a internal MCE visual aid image, then skip this one.
if (tinyMCE.getAttrib(img, 'name').indexOf('mce_') == 0)
return true;
src = tinyMCE.getAttrib(img, 'src');
alt = tinyMCE.getAttrib(img, 'alt');
// Try polling out the title
if (alt == "")
alt = tinyMCE.getAttrib(img, 'title');
// Fix width/height attributes if the styles is specified
if (tinyMCE.isGecko) {
var w = img.style.width;
if (w != null && w != "")
img.setAttribute("width", w);
var h = img.style.height;
if (h != null && h != "")
img.setAttribute("height", h);
}
border = tinyMCE.getAttrib(img, 'border');
hspace = tinyMCE.getAttrib(img, 'hspace');
vspace = tinyMCE.getAttrib(img, 'vspace');
width = tinyMCE.getAttrib(img, 'width');
height = tinyMCE.getAttrib(img, 'height');
align = tinyMCE.getAttrib(img, 'align');
onmouseover = tinyMCE.getAttrib(img, 'onmouseover');
onmouseout = tinyMCE.getAttrib(img, 'onmouseout');
title = tinyMCE.getAttrib(img, 'title');
// Is realy specified?
if (tinyMCE.isMSIE) {
width = img.attributes['width'].specified ? width : "";
height = img.attributes['height'].specified ? height : "";
}
src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);");
// Use mce_src if defined
mceRealSrc = tinyMCE.getAttrib(img, 'mce_src');
if (mceRealSrc != "") {
src = mceRealSrc;
if (tinyMCE.getParam('convert_urls'))
src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);");
}
action = "update";
}
return {'src' : src, 'alt' : alt, 'border' : border, 'hspace' : hspace, 'vspace' : vspace,
'width' : width, 'height' : height, 'align' : align, 'title' : title,
'onmouseover' : onmouseover, 'onmouseout' : onmouseout, 'action' : action};
}
// Get all the files in the attached files list that have been
// recognised as images.
function attachedImageList() {
// All the rows in the attached files list:
var attachrows = getElementsByTagAndClassName('tbody', null, 'attachedfiles')[0].childNodes;
// Go through the rows, and for all the rows where the first cell
// contains an 'image' image, return the row id (id attribute) and
// the filename (contents of the second cell)
return map(function(r) { return {'id':r.id, 'name':scrapeText(r.childNodes[1])}; },
filter(function(r) { return r.firstChild.firstChild.alt == 'image'; }, attachrows));
}
function insertImage() {
var form = $('insertimageform');
var alt = form.imgid.value;
var src = imageSrcFromId(alt);
var border = form.border.value;
var vspace = form.vspace.value;
var hspace = form.hspace.value;
var height = form.height.value;
var width = form.width.value;
var align = form.align.value;
tinyMCE.themes['advanced']._insertImage(src, alt, border, hspace, vspace,
width, height, align, '', '', '');
replaceChildNodes('insertimage', null);
}
function resetImageData() {
var form = $('insertimageform');
form.width.value = form.height.value = "";
}
var preloadImage = new Image();
function updateImageData() {
var form = $('insertimageform');
if (form.width.value == "") {
form.width.value = preloadImage.width;
}
if (form.height.value == "") {
form.height.value = preloadImage.height;
}
}
function imageSrcFromId(imageid) {
var idparts = imageid.split(':');
if (idparts[0] == 'artefact') {
return config.wwwroot + 'artefact/file/download.php?file=' + idparts[1];
}
if (idparts[0] == 'uploaded') {
return config.wwwroot + 'artefact/blog/downloadtemp.php?uploadnumber=' + idparts[1] +
'&createid=' + {$createid};
}
return '';
}
function getImageData(imageid) {
preloadImage = new Image();
preloadImage.onload = updateImageData;
preloadImage.onerror = function () {
var form = $('insertimageform');
form.width.value = form.height.value = "";
};
var imgsrc = imageSrcFromId(imageid);
$('insertimageform').imgsrc.value = imgsrc;
$('insertimageform').imgid.value = imageid;
preloadImage.src = imgsrc;
}
function imageSelector(imageid) {
var imagefiles = attachedImageList();
if (imagefiles.length == 0) {
return SPAN({'id':'imageselector'}, {$getstring['noimageshavebeenattachedtothispost']});
}
else {
var sel = SELECT({'class':'select', 'id':'imageselector'});
appendChildNodes(sel, OPTION({'value':''}, '--'));
for (var i = 0; i < imagefiles.length; i++) {
if (imageid == imagefiles[i].id) {
appendChildNodes(sel, OPTION({'value':imagefiles[i].id, 'selected':true},
imagefiles[i].name));
}
else {
appendChildNodes(sel, OPTION({'value':imagefiles[i].id}, imagefiles[i].name));
}
}
sel.onchange = function () {
resetImageData();
getImageData(sel.value);
};
return sel;
}
}
function alignSelector(align) {
var sel = SELECT({'name':'align', 'class':'select'});
var options = {'' : '--',
'baseline': {$getstring['baseline']},
'top': {$getstring['top']},
'middle': {$getstring['middle']},
'bottom': {$getstring['bottom']},
'texttop': {$getstring['texttop']},
'absmiddle': {$getstring['absolutemiddle']},
'absbottom': {$getstring['absolutebottom']},
'left': {$getstring['left']},
'right': {$getstring['right']}};
for (option in options) {
if (align == option) {
appendChildNodes(sel, OPTION({'value':option, 'selected':true}, options[option]));
}
else {
appendChildNodes(sel, OPTION({'value':option}, options[option]));
}
}
return sel;
}
function blogpostExecCommandHandler(editor_id, elm, command, user_interface, value) {
var linkElm, imageElm, inst;
switch (command) {
case "mceImage":
a = getSelectedImgAttributes(editor_id);
var tbody = TBODY(null,
TR(null, TH({'colSpan':2}, LABEL(null,{$getstring['insertimage']}))),
TR(null, TH(null, LABEL(null,{$getstring['name']})),
TD(null, imageSelector(a.alt))),
TR(null, TH(null, LABEL(null,{$getstring['alignment']})),
TD(null, alignSelector(a.align))),
TR(null, TH(null, LABEL(null,{$getstring['dimensions']})),
TD(null,INPUT({'type':'text', 'class':'text', 'name':'width', 'size':3, 'value':a.width}),
' x ', INPUT({'type':'text', 'class':'text', 'name':'height', 'size':3, 'value':a.height}))),
TR(null, TH(null, LABEL(null,{$getstring['border']})),
TD(null,INPUT({'type':'text', 'class':'text', 'name':'border', 'size':3, 'value':a.border}))),
TR(null, TH(null, LABEL(null,{$getstring['verticalspace']})),
TD(null,INPUT({'type':'text', 'class':'text', 'name':'vspace', 'size':3, 'value':a.vspace}))),
TR(null, TH(null, LABEL(null,{$getstring['horizontalspace']})),
TD(null,INPUT({'type':'text', 'class':'text', 'name':'hspace', 'size':3, 'value':a.hspace}))));
var imageform = FORM({'id':'insertimageform'},
INPUT({'type':'hidden', 'name':'imgsrc', 'value':''}),
INPUT({'type':'hidden', 'name':'imgid', 'value':a.alt}),
TABLE(null,tbody));
appendChildNodes(tbody, TR(null,TD({'colSpan':2},
INPUT({'type':'button', 'class':'button',
'value':(a.src == '' ? {$getstring['insert']} : {$getstring['update']}),
'onclick':function () { insertImage(); }}),
INPUT({'type':'button', 'class':'button', 'value':{$getstring['cancel']},
'onclick':function () { replaceChildNodes('insertimage', null); }}))));
replaceChildNodes('insertimage', imageform);
return true;
}
return false;
}
EOF;
// Override the default Mahara tinyMCE.init(); Add an image button and
// the execcommand_callback.
$tinymceinit = <<<EOF
<script type="text/javascript">
tinyMCE.init({
mode: "textareas",
editor_selector: 'wysiwyg',
button_tile_map: true,
theme: "advanced",
plugins: "table,emotions,iespell,inlinepopups",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,separator,forecolor,backcolor,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,hr,emotions,iespell,cleanup,separator,link,unlink,image",
theme_advanced_buttons2 : "tablecontrols,separator,cut,copy,paste",
theme_advanced_buttons3 : "fontselect,separator,fontsizeselect,separator,formatselect",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "center",
content_css : config.themeurl + 'style/tinymce.css',
execcommand_callback : "blogpostExecCommandHandler"
});
</script>
EOF;
$draftform = pieform(array(
'name' => 'draftpost',
'method' => 'post',
'action' => '',
'elements' => array(
'thisisdraft' => array(
'type' => 'checkbox',
'title' => get_string('thisisdraft', 'artefact.blog'),
'description' => get_string('thisisdraftdesc', 'artefact.blog'),
'defaultvalue' => $checked
),
)
));
$smarty = smarty(array('tablerenderer', 'artefact/file/js/file.js'));
$smarty = smarty(array('tablerenderer', 'artefact/file/js/file.js'),
array(), array(), array('tinymceinit' => $tinymceinit));
$smarty->assign('INLINEJAVASCRIPT', $javascript);
$smarty->assign_by_ref('textinputform', $form);
$smarty->assign_by_ref('textinputform', $textinputform);
$smarty->assign_by_ref('draftform', $draftform);
$smarty->assign('pagetitle', $pagetitle);
$smarty->display('artefact:blog:editpost.tpl');
......
......@@ -29,6 +29,7 @@ defined('INTERNAL') || die();
$string['blog'] = 'Blog';
$string['addblog'] = 'Add Blog';
$string['addpost'] = 'Add Post';
$string['alignment'] = 'Alignment';
$string['attach'] = 'Attach';
$string['attachedfilelistloaded'] = 'Attached file list loaded';
$string['attachedfiles'] = 'Attached files';
......@@ -41,6 +42,7 @@ $string['blogpostsaved'] = 'Blog post saved';
$string['blogsettings'] = 'Blog Settings';
$string['blogtitle'] = 'Title';
$string['blogtitledesc'] = 'e.g., ‘Jill’s Nursing Practicum Journal’.';
$string['border'] = 'Border';
$string['browsemyfiles'] = 'Browse my files';
$string['cancel'] = 'Cancel';
$string['commentsallowed'] = 'Comments';
......@@ -57,12 +59,17 @@ $string['createblog'] = 'Create Blog';
$string['delete'] = 'Delete';
$string['deleteblogpost?'] = 'Are you sure you want to delete this post?';
$string['description'] = 'Description';
$string['dimensions'] = 'Dimensions';
$string['draft'] = 'Draft';
$string['edit'] = 'Edit';
$string['editblogpost'] = 'Edit Blog Post';
$string['erroraccessingblogfilesfolder'] = 'Error accessing blogfiles folder';
$string['errorsavingattachments'] = 'An error occurred while saving blog post attachments';
$string['horizontalspace'] = 'Horizontal space';
$string['insert'] = 'Insert';
$string['insertimage'] = 'Insert image';
$string['myblogs'] = 'My Blogs';
$string['name'] = 'Name';
$string['newblog'] = 'New Blog';
$string['newblogpost'] = 'New Blog Post';
$string['nofilesattachedtothispost'] = 'No attached files';
......@@ -86,8 +93,20 @@ $string['settings'] = 'Settings';
$string['thisisdraft'] = 'This post is a draft';
$string['thisisdraftdesc'] = 'When your post is a draft, no one except you can see it.';
$string['title'] = 'Title';
$string['update'] = 'Update';
$string['verticalspace'] = 'Vertical space';
$string['viewblog'] = 'View Blog';
$string['youarenottheownerofthisblogpost'] = 'You are not the owner of this blog post';
$string['cannotdeleteblogpost'] = 'An error occured removing this blog post.';
$string['baseline'] = 'Baseline';
$string['top'] = 'Top';
$string['middle'] = 'Middle';
$string['bottom'] = 'Bottom';
$string['texttop'] = 'Text top';
$string['absolutemiddle'] = 'Absolute middle';
$string['absolutebottom'] = 'Absolute bottom';
$string['left'] = 'Left';
$string['right'] = 'Right';
?>
......@@ -586,6 +586,13 @@ class ArtefactTypeBlogPost extends ArtefactType {
// Where to store temporary blog post files under dataroot
static $blogattachmentroot = 'artefact/blog/uploads/';
public static function get_temp_file_path($createid, $uploadnumber) {
return get_config('dataroot') . self::$blogattachmentroot
. session_id() . $createid . '/' . $uploadnumber;
}
/**
* This function saves an uploaded file to a temporary directory in dataroot
*
......@@ -636,7 +643,7 @@ class ArtefactTypeBlogPost extends ArtefactType {
$data->file = $fileid;
insert_record('artefact_blog_blogpost_file', $data);
return true;
return $fileid;
}
public static function blogfiles_folder_id() {
......
......@@ -91,12 +91,36 @@ foreach ($artefacts as $a) {
// Add the newly uploaded files to myfiles and then to the blog post.
$uploadartefact = array();
if (!empty($uploads)) {
foreach ($uploads as $upload) {
if (!$postobj->save_attachment(session_id() . $createid, $upload->id,
$upload->title, $upload->description)) {
if (!$fileid = $postobj->save_attachment(session_id() . $createid, $upload->id,
$upload->title, $upload->description)) {
json_reply('local', get_string('errorsavingattachments', 'artefact.blog'));
// Things could be in a bad state.
}
$uploadartefact[$upload->id] = $fileid;
}
}
// <img> tags in the body of the post may refer to newly uploaded
// files. Because these files have been moved to permanent locations,
// we need to go through the body of the post and change the 'src' and
// 'alt' attributes of all images that refer to uploaded files.
if (!empty($uploadartefact)) {
$originalbody = $body;
foreach ($uploadartefact as $k => $v) {
$regexps = array('/\/artefact\/blog\/downloadtemp.php\?uploadnumber=' . $k .'&amp;createid=\d+/',
'/alt="uploaded:' . $k . '"/');
$subs = array('/artefact/file/download.php?file=' . $v,
'alt="artefact:' . $v . '"');
$body = preg_replace($regexps, $subs, $body);
}
if ($body != $originalbody) {
$postobj = new ArtefactTypeBlogPost($blogpost, null);
$postobj->set('description', $body);
$postobj->commit();
}
}
......
......@@ -12,6 +12,7 @@
{include file="columnleftstart.tpl"}
<h2>{str section="artefact.blog" tag=$pagetitle}</h2>
{$textinputform}