Commit d268d11b authored by Robert Lyon's avatar Robert Lyon
Browse files

Allow site_content to be institution specific (bug #1254299)



Changes include:
- added an institution column to the site_content table
- added an 'Edit site pages' page under Admin -> Institutions
that is accessibe by institution admins
- added an 'institution' option to the edit site pages form - this is
a hidden field if user can edit only one institution.

On upgrade it updates the site_content table to give current data the
institution on 'mahara' (incl. local site pages) and for each
institution it replicates the data already in the db for the default site (excl.
local site pages) so that every site has their own versions, which can
be adjusted as one sees fit.

On creation of new institution it creates the rows in site_content
table but with the default strings (like what you see when you first
install a mahara) but sets the sitepages column in institution table
to default (mahara). On deletion of institution it removes the rows in
site_content.

A user on login sees the institution site page based on what
institution theme they see.

On logout the 'lastinstitution' cookie is set allowing for them to see
institution specific site pages.

The 'No institution' (mahara) site pages can only be edited through
Configure site -> Edit site pages.

Also allow for an institution site page to be viewed if 'institution'
variable is passed to it eg terms.php?institution=testing allowing for
another way to access info when logged out.

Change-Id: I2ed30b63c15bf676d83eb2231f48c4ca23ce8b53
Signed-off-by: Robert Lyon's avatarRobert Lyon <robertl@catalyst.net.nz>
parent d9248922
......@@ -10,20 +10,27 @@
*/
define('INTERNAL', 1);
define('ADMIN', 1);
define('INSTITUTIONALADMIN', 1);
define('JSON', 1);
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
$contentname = param_alpha('contentname');
if (!$contentitem = get_record('site_content', 'name', $contentname)) {
json_reply('local', get_string('loadsitecontentfailed', 'admin', get_string($contentname, 'admin')));
$institution = param_alpha('institution', null);
if (empty($institution)) {
$institution = 'mahara';
}
if (!$contentitem = get_record('site_content', 'name', $contentname, 'institution', $institution)) {
// This might be a local site page (or otherwise missing) so we will try and load the 'mahara' version
if (!$contentitem = get_record('site_content', 'name', $contentname, 'institution', 'mahara')) {
json_reply('local', get_string('loadsitecontentfailed', 'admin', get_string($contentname, 'admin')));
}
}
$pageusedefault = get_record('institution_config', 'institution', $institution, 'field', 'sitepages_' . $contentname);
$data = array(
'contentname' => $contentname,
'content' => $contentitem->content,
'pageusedefault' => (!empty($pageusedefault->value) && $pageusedefault->value == 'mahara') ? 1 : 0,
'error' => false,
'message' => false,
);
......
......@@ -29,6 +29,7 @@ if ($pagenames = array_merge($corepagenames, $localpagenames)) {
'site_content', 'name IN (' . join(',', array_fill(0, count($pagenames), '?')) . ')', $pagenames
);
}
$pageoptions = array();
foreach ($sitepages as $page) {
$section = in_array($page->name, $localpagenames) ? 'local' : 'admin';
......@@ -44,6 +45,7 @@ $form = pieform(array(
'jsform' => true,
'jssuccesscallback' => 'contentSaved',
'elements' => array(
'pageinstitution' => array('type' => 'hidden', 'value' => 'mahara'),
'pagename' => array(
'type' => 'select',
'title' => get_string('pagename', 'admin'),
......@@ -77,8 +79,9 @@ function editsitepage_submit(Pieform $form, $values) {
$data->content = $values['pagetext'];
$data->mtime = db_format_timestamp(time());
$data->mauthor = $USER->get('id');
$data->institution = 'mahara';
try {
update_record('site_content', $data, 'name');
update_record('site_content', $data, array('name', 'institution'));
}
catch (SQLException $e) {
$form->reply(PIEFORM_ERR, get_string('savefailed', 'admin'));
......
<?php
/**
*
* @package mahara
* @subpackage admin
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*
*/
define('INTERNAL', 1);
define('INSTITUTIONALADMIN', 1);
define('MENUITEM', 'manageinstitutions/sitepages');
define('SECTION_PLUGINTYPE', 'core');
define('SECTION_PLUGINNAME', 'admin');
define('SECTION_PAGE', 'sitepages');
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
define('TITLE', get_string('editinstitutionsitepages', 'admin'));
require_once('pieforms/pieform.php');
require_once('license.php');
define('DEFAULTPAGE', 'home');
require_once('institution.php');
$sitepages = array();
$corepagenames = site_content_pages();
$localpagenames = function_exists('local_site_content_pages') ? local_site_content_pages() : array();
if ($pagenames = array_merge($corepagenames, $localpagenames)) {
$sitepages = get_records_select_array(
'site_content', 'name IN (' . join(',', array_fill(0, count($pagenames), '?')) . ')', $pagenames
);
}
$pageoptions = array();
$institutionselector = get_institution_selector(false);
if (!empty($institutionselector['options']) && sizeof($institutionselector['options']) > 1) {
$institutionselector['defaultvalue'] = key($institutionselector['options']);
}
else if (!empty($institutionselector['options']) && sizeof($institutionselector['options']) == 1) {
// Institutional admins with only 1 institution do not get institution dropdown
// Same with admins and only one institution exists
$institutionselector = array('type' => 'hidden',
'value' => key($institutionselector['options']),
'defaultvalue' => key($institutionselector['options']),
);
}
else if (empty($institutionselector['options'])) {
// Only the 'no institution' institution exists so we need to display this fact
$smarty = smarty(array(), array(), array());
$smarty->assign('noinstitutionsadmin', (($USER->admin) ? get_string('noinstitutionsitepagesadmin', 'admin', get_config('wwwroot') . 'admin/site/pages.php') : false));
$smarty->assign('noinstitutions', get_string('noinstitutionsitepages', 'admin'));
$smarty->assign('PAGEHEADING', TITLE);
$smarty->display('admin/site/pages.tpl');
exit;
}
foreach ($sitepages as $page) {
$section = in_array($page->name, $localpagenames) ? 'local' : 'admin';
$pageoptions[$page->name] = get_string($page->name, $section);
$pagecontents[$page->name] = $page->content;
}
asort($pageoptions);
$getstring = array('discardpageedits' => json_encode(get_string('discardpageedits', 'admin')));
$form = pieform(array(
'name' => 'editsitepage',
'jsform' => true,
'jssuccesscallback' => 'contentSaved',
'elements' => array(
'pageinstitution' => $institutionselector,
'pagename' => array(
'type' => 'select',
'title' => get_string('pagename', 'admin'),
'defaultvalue' => DEFAULTPAGE,
'options' => $pageoptions
),
'pageusedefault' => array(
'type' => 'checkbox',
'title' => get_string('usedefault', 'admin'),
'description' => get_string('usedefaultdescription', 'admin'),
'defaultvalue' => (get_config_institution($institutionselector['defaultvalue'], 'sitepages_' . DEFAULTPAGE) == 'mahara' ? 1 : 0),
),
'pagetext' => array(
'name' => 'pagetext',
'type' => 'wysiwyg',
'rows' => 25,
'cols' => 100,
'title' => get_string('pagetext', 'admin'),
'defaultvalue' => $pagecontents[DEFAULTPAGE],
'rules' => array(
'maxlength' => 65536,
'required' => true
)
),
'submit' => array(
'type' => 'submit',
'value' => get_string('savechanges', 'admin')
),
)
));
function editsitepage_validate(Pieform $form, $values) {
$allowedinstitutions = get_institution_selector(false);
if (array_search($values['pageinstitution'], array_flip($allowedinstitutions['options'])) === false) {
$form->set_error(null, get_string('pageinstitutionbad', 'admin', $values['pageinstitution']));
}
}
function editsitepage_submit(Pieform $form, $values) {
global $USER;
$data = new StdClass;
$data->name = $values['pagename'];
if (empty($values['pageusedefault'])) {
$data->content = $values['pagetext'];
}
$data->mtime = db_format_timestamp(time());
$data->mauthor = $USER->get('id');
$data->institution = $values['pageinstitution'];
// update the institution config if needed
if (isset($values['pageusedefault'])) {
$configdata = new StdClass;
$configdata->institution = $data->institution;
$configdata->field = 'sitepages_' . $data->name;
$whereobj = clone $configdata;
$configdata->value = !empty($values['pageusedefault']) ? 'mahara' : $data->institution;
ensure_record_exists('institution_config', $whereobj, $configdata);
}
if (get_record('site_content', 'name', $data->name, 'institution', $data->institution)) {
try {
update_record('site_content', $data, array('name', 'institution'));
}
catch (SQLException $e) {
$form->reply(PIEFORM_ERR, get_string('savefailed', 'admin'));
}
}
else {
// local site page doesn't exist for this institution so we shall add it
$data->ctime = db_format_timestamp(time());
try {
insert_record('site_content', $data);
}
catch (SQLException $e) {
$form->reply(PIEFORM_ERR, get_string('savefailed', 'admin'));
}
}
$form->reply(PIEFORM_OK, get_string('pagesaved', 'admin'));
}
$smarty = smarty(array('adminsitepages'), array(), array('admin' => array('discardpageedits')));
$smarty->assign('noinstitutionsadmin', (($USER->admin) ? get_string('noinstitutionsitepagesadmin', 'admin', get_config('wwwroot') . 'admin/site/pages.php') : false));
$smarty->assign('pageeditform', $form);
$smarty->assign('PAGEHEADING', TITLE);
$smarty->display('admin/site/pages.tpl');
......@@ -157,6 +157,8 @@ if ($institution || $add) {
delete_records('view_access', 'institution', $values['i']);
delete_records('institution_data', 'institution', $values['i']);
delete_records('institution_registration', 'institution', $values['i']);
delete_records('site_content', 'institution', $values['i']);
delete_records('institution_config', 'institution', $values['i']);
delete_records('institution', 'name', $values['i']);
db_commit();
......@@ -770,6 +772,26 @@ function institution_submit(Pieform $form, $values) {
);
insert_record('auth_instance', $authinstance);
}
// We need to add the default lines to the site_content table for this institution
// We also need to set the institution to be using default site pages to begin with
// so that using custom institution pages is an opt-in situation
$pages = site_content_pages();
$now = db_format_timestamp(time());
foreach ($pages as $name) {
$page = new stdClass();
$page->name = $name;
$page->ctime = $now;
$page->mtime = $now;
$page->content = get_string($page->name . 'defaultcontent', 'install', get_string('sitepageconfiginstitution', 'install'));
$page->institution = $newinstitution->name;
insert_record('site_content', $page);
$institutionconfig = new stdClass();
$institutionconfig->institution = $newinstitution->name;
$institutionconfig->field = 'sitepages_' . $name;
$institutionconfig->value = 'mahara';
insert_record('institution_config', $institutionconfig);
}
}
if (is_null($newinstitution->style) && !empty($oldinstitution->style)) {
......
......@@ -2122,6 +2122,7 @@ function auth_generate_registration_form_js($aform, $registerconfirm) {
';
}
else {
$url = get_config('wwwroot') . 'json/termsandconditions.php';
$js = '
var registerconfirm = ' . json_encode($registerconfirm) . ';
$j(function() {
......@@ -2136,6 +2137,21 @@ function auth_generate_registration_form_js($aform, $registerconfirm) {
$j("#' . $reasonid . '_container textarea").addClass("js-hidden");
$j("#' . $reasonid . '_container").next("tr.textarea").addClass("js-hidden");
}
// need to fetch the correct terms and conditions for the institution
if (this.value) {
$j.ajax({
type: "POST",
dataType: "json",
url: "' . $url . '",
data: {
"institution": this.value,
}
}).done(function (data) {
if (data.content) {
$j("#termscontainer").html(data.content);
}
});
}
});
});
';
......
......@@ -714,6 +714,45 @@ class User {
}
}
/**
* Get institution name by checking which 'institution theme' a user is allocated to see
* and if that theme has sitepages set.
* Or if a lastinstitution cookie is set. Or if an institution url parameter is set.
* Defaults to 'mahara'.
*
* @return string Institution name
*/
public function sitepages_institutionname_by_theme($page) {
// get institution when logged in
if ($this->is_logged_in()) {
if ($theme = $this->get('institutiontheme')) {
if (!empty($theme->institutionname)) {
// check to see if institution is using it's own site pages or default site pages
if ($institution = get_record('institution', 'name', $theme->institutionname)) {
if (get_config_institution($institution->name, 'sitepages_' . $page)) {
return get_config_institution($institution->name, 'sitepages_' . $page);
}
}
else {
return $theme->institutionname;
}
}
else {
return 'mahara';
}
}
}
// or from url
if ($institution = param_alphanum('institution', null)) {
return $institution;
}
// or from cookie
if ($institution = get_cookie('lastinstitution')) {
return $institution;
}
return 'mahara';
}
public function in_institution($institution, $role = null) {
$institutions = $this->get('institutions');
return isset($institutions[$institution])
......@@ -1398,6 +1437,9 @@ class LiveUser extends User {
* Logs the current user out
*/
public function logout () {
// add long-term cookie to record institution user last used
set_cookie('lastinstitution', $this->sitepages_institutionname_by_theme('loggedouthome'), '2240561472', true);
require_once(get_config('libroot') . 'ddl.php');
if ($this->changed == true) {
......
......@@ -9,10 +9,11 @@
var oldPageContent = '';
var oldPageName = 'home';
var changedCheckbox = false;
var checkOldContent = false;
function updateWYSIWYGText() {
if (checkOldContent && oldPageContent != tinyMCE.activeEditor.getContent() && !confirm(get_string('discardpageedits', 'admin'))) {
if (((checkOldContent && oldPageContent != tinyMCE.activeEditor.getContent()) || changedCheckbox) && !confirm(get_string('discardpageedits', 'admin'))) {
$('editsitepage_pagename').value = oldPageName;
return;
}
......@@ -21,25 +22,58 @@ function updateWYSIWYGText() {
checkOldContent = true;
}
sendjsonrequest(
'editchangecontent.json.php',
{'contentname' :$('editsitepage_pagename').value},
config['wwwroot'] + 'admin/site/editchangecontent.json.php',
{'contentname' : $('editsitepage_pagename').value,
'institution' : $('editsitepage_pageinstitution').value
},
'POST',
function(data) {
if (!data.error) {
tinyMCE.activeEditor.setContent(data.content);
oldPageContent = tinyMCE.activeEditor.getContent();
oldPageName = $('editsitepage_pagename').value;
if ($('editsitepage_pageusedefault')) {
$('editsitepage_pageusedefault').checked = (data.pageusedefault) ? true : false;
updateSiteDefault(false);
}
}
}
);
}
function updateSiteDefault(changed) {
changedCheckbox = (changed) ? true : false;
if ($('editsitepage_pageusedefault').checked == true) {
tinyMCE.activeEditor.getBody().setAttribute('contenteditable', false);
$('changecheckboxdiv').style.display = 'block';
$('changecheckboxdiv').style.zIndex = '5';
$('changecheckboxdiv').style.position = 'absolute';
$('changecheckboxdiv').style.width = $('editsitepage_pagetext_tbl').offsetWidth + 'px';
$('changecheckboxdiv').style.height = $('editsitepage_pagetext_tbl').offsetHeight + 'px';
$('changecheckboxdiv').style.top = elementPosition('editsitepage_pagetext_tbl').y + 'px';
$('changecheckboxdiv').style.left = elementPosition('editsitepage_pagetext_tbl').x + 'px';
}
else {
tinyMCE.activeEditor.getBody().setAttribute('contenteditable', true);
$('changecheckboxdiv').style.display = 'none';
$('changecheckboxdiv').style.width = '1px';
$('changecheckboxdiv').style.height = '1px';
}
}
function connectElements() {
connect('editsitepage_pagename', 'onchange', updateWYSIWYGText);
connect('editsitepage_pageinstitution', 'onchange', updateWYSIWYGText);
if ($('editsitepage_pageusedefault')) {
connect('editsitepage_pageusedefault', 'onchange', updateSiteDefault);
}
// create hidden div to place over tinymce to 'show' when it is disabled from editing
appendChildNodes($('editsitepage'), DIV({'id':'changecheckboxdiv','style':'display:none;background-color: rgba(200,200,200,0.5)'}, ''));
}
function contentSaved(form, data) {
connectElements();
changedCheckbox = false;
if (!tinyMCE.isMSIE) {
// Disabling changed content check for IE; Need to work out
// why the getBody() call in getContent fails to return the
......@@ -51,5 +85,11 @@ function contentSaved(form, data) {
addLoadEvent(function() {
connectElements();
updateWYSIWYGText();
// need to wait until tinyMCE editor is loaded before updating editor's text
var checkExists = setInterval(function() {
if (tinyMCE.activeEditor != "null") {
updateWYSIWYGText();
clearInterval(checkExists);
}
}, 500);
});
<?php
/**
*
* @package mahara
* @subpackage core
* @author Catalyst IT Ltd
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
* @copyright For copyright information on Mahara, please see the README file distributed with this software.
*
*/
define('INTERNAL', 1);
define('PUBLIC', 1);
define('JSON', 1);
define('NOSESSKEY', 1);
require(dirname(dirname(__FILE__)) . '/init.php');
$institution = param_alphanum('institution', 'mahara');
if (empty($institution)) { // if '0' is passed via the form we display the default terms and conditions
$institution = 'mahara';
}
$useterms = false;
if ($institution != 'mahara') {
// try to fetch institution's terms and conditions
$useterms = get_record_sql("SELECT sc.content FROM {site_content} sc
LEFT JOIN {institution_config} ic ON ic.value = sc.institution
WHERE ic.field = ?
AND sc.name = ?
AND ic.institution = ?",
array('sitepages_termsandconditions', 'termsandconditions', $institution));
}
if (empty($useterms)) {
// get the default terms and conditions
$useterms = get_record_sql("SELECT content FROM {site_content}
WHERE institution = ?
AND name = ?", array($institution, 'termsandconditions'));
}
json_headers();
print json_encode($useterms);
......@@ -72,6 +72,11 @@ $string['manageinstitutions'] = 'Manage institutions';
$string['siteoptions'] = 'Site options';
$string['siteoptionsdescription'] = 'Configure basic site options such as the name, language and theme';
$string['editsitepages'] = 'Edit site pages';
$string['editinstitutionsitepages'] = 'Edit institution site pages';
$string['pageinstitutionbad'] = "You can't access and/or edit site pages for Institution '%s'";
$string['institutionsitepages'] = 'Institution site pages';
$string['usedefault'] = 'Use site default';
$string['usedefaultdescription'] = 'Use the site\'s default \'site pages\' text for this particular page type instead.';
$string['editsitepagesdescription'] = 'Edit the content of various pages around the site';
$string['menus'] = 'Menus';
$string['menusdescription'] = 'Manage the links and files within the "Links and resources" and footer menus';
......@@ -909,6 +914,8 @@ $string['Admins'] = 'Administrators';
$string['noinstitutions'] = 'No institutions';
$string['noinstitutionsdescription'] = 'If you would like to associate users with an institution, you should create the institution first.';
$string['noinstitutionsstatsdescription'] = 'Institution statistics are not available because there are no institutions available to your user.';
$string['noinstitutionsitepages'] = 'You do not have permission to edit any institution site pages or no institutions have been created yet.';
$string['noinstitutionsitepagesadmin'] = 'If you are a site admin please edit the default site pages in <a href="%s">Configure site</a>.';
$string['Lockedfields'] = 'Locked fields';
$string['disabledlockedfieldhelp'] = 'Note: Disabled checkboxes are for profile fields which are locked in the institution settings for "%s". These profile fields are locked at the site level and cannot be unlocked here.';
......
<!-- @license http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later -->
<!-- @copyright For copyright information on Mahara, please see the README file distributed with this software. -->
<h3>Institution site pages</h3>
<p>The site pages that users see if they are logged in (or logged out users whose browser retains the Mahara institution cookie from a previous login). If <strong>Site default</strong> is selected they will see the site's default site pages.</p>
<p>You may choose any institution's site pages, but will only be able to edit the institution site pages for the institution(s) that you are admin of.</p>
......@@ -28,14 +28,14 @@ $string['homedefaultcontent'] = '<h1>Welcome</h1>
<p>For more information you can read <a href="about.php">About</a> <strong>[<i>please ensure you also edit this page</i>]</strong> or alternatively please feel free to <a href="contact.php">contact us</a>.</p>
<p><i>You can edit this text via "Edit site pages" in "Configure site" in "Site administration"</i></p>';
<p><i>You can edit this text via %s</i></p>';
$string['loggedouthomedefaultcontent'] = '<h1>Welcome</h1>
<p>[<i>Name of your installation here</i>] is a fully featured electronic portfolio system with social networking features to create online learning communities.</p>
<p>For more information you can read <a href="about.php">About</a> [<i>please ensure you also edit this page</i>] or alternatively please feel free to <a href="contact.php">contact us</a>.</p>
<p><i>You can edit this text via "Edit site pages" in "Configure site" in "Site administration"</i></p>';
<p><i>You can edit this text via %s</i></p>';
$string['privacydefaultcontent'] = '<h1>Privacy statement</h1>
<h2>Introduction</h2>
......@@ -128,3 +128,6 @@ $string['licenseshortnamebyncsa'] = 'CC-BY-NC-SA-3.0';
$string['licenseshortnamebync'] = 'CC-BY-NC-3.0';
$string['licenseshortnamebyncnd'] = 'CC-BY-NC-ND-3.0';
$string['licenseshortnamegfdl'] = 'GFDL-1.3';
$string['sitepageconfigdefault'] = '"Edit site pages" in "Configure site" in "Site administration"';
$string['sitepageconfiginstitution'] = '"Edit site pages" in "Institutions" in "Site administration"';
......@@ -963,10 +963,12 @@
<FIELD NAME="ctime" TYPE="datetime" NOTNULL="true" />
<FIELD NAME="mtime" TYPE="datetime" NOTNULL="true" />
<FIELD NAME="mauthor" TYPE="int" LENGTH="10" NOTNULL="false" />
<FIELD NAME="institution" TYPE="char" LENGTH="255" NOTNULL="true"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="name" />
<KEY NAME="primary" TYPE="primary" FIELDS="name,institution" />
<KEY NAME="mauthorfk" TYPE="foreign" FIELDS="mauthor" REFTABLE="usr" REFFIELDS="id" />
<KEY NAME="institutionfk" TYPE="foreign" FIELDS="institution" REFTABLE="institution" REFFIELDS="name"/>
</KEYS>
</TABLE>
<!-- watchlist stuff -->
......
......@@ -2928,5 +2928,53 @@ function xmldb_core_upgrade($oldversion=0) {
create_table($table);
}
if ($oldversion < 2014010801) {
// adding institution column to allow for different site content for each institution
$table = new XMLDBTable('site_content');
$field = new XMLDBField('institution');
$field->setAttributes(XMLDB_TYPE_CHAR, 255, null, null);
add_field($table, $field);
// resetting the primary key and updating what is currently there to be
// the 'mahara' institution's site pages
$key = new XMLDBKey('primary');
$key->setAttributes(XMLDB_KEY_PRIMARY, array('name'));
drop_key($table, $key);
execute_sql("UPDATE {site_content} SET institution = ?", array('mahara'));
$key = new XMLDBKey('primary');
$key->setAttributes(XMLDB_KEY_PRIMARY, array('name', 'institution'));
add_key($table, $key);
$key = new XMLDBKey('institutionfk');
$key->setAttributes(XMLDB_KEY_FOREIGN, array('institution'), 'institution', array('name'));
add_key($table, $key);
// now add the default site pages for each existing institution with the values of
// the 'mahara' institution. These can them be altered via Admin -> Institution -> Edit site pages
$sitecontentarray = array();
$sitecontents = get_records_array('site_content', 'institution', 'mahara');
foreach ($sitecontents as $sitecontent) {
$sitecontentarray[$sitecontent->name] = $sitecontent->content;
}
$pages = site_content_pages();
$now = db_format_timestamp(time());
$institutions = get_records_array('institution');
foreach ($institutions as $institution) {
if ($institution->name != 'mahara') {
foreach ($pages as $name) {
$page = new stdClass();
$page->name = $name;
$page->ctime = $now;
$page->mtime = $now;
$page->content = $sitecontentarray[$name];
$page->institution = $institution->name;
insert_record('site_content', $page);
}
}
}
}