Commit 3dae4e71 authored by Aaron Wells's avatar Aaron Wells Committed by Gerrit Code Review
Browse files

Skins: Institution setting to enable/disable for their users

Bug1168213

Change-Id: Id23b2d6c163def4365d17e26b6c701a4cdadc948
parent 189646a1
......@@ -249,6 +249,7 @@ if ($institution || $add) {
$data->licensemandatory = 0;
$data->licensedefault = '';
$data->dropdownmenu = get_config('dropdownmenu') ? 1 : 0;
$data->skins = get_config('skins') ? 1 : 0;
$lockedprofilefields = array();
$authtypes = auth_get_available_auth_types();
......@@ -395,6 +396,14 @@ if ($institution || $add) {
'defaultvalue' => $data->dropdownmenu,
'help' => true,
);
if (get_config('skins')) {
$elements['skins'] = array(
'type' => 'checkbox',
'title' => get_string('skins', 'admin'),
'description' => get_string('skinsinstitutiondescription', 'admin'),
'defaultvalue' => $data->skins,
);
}
$elements['customthemefs'] = array(
'type' => 'fieldset',
'class' => 'customtheme' . ($elements['theme']['defaultvalue'] != 'custom' ? ' js-hidden' : ''),
......@@ -506,7 +515,7 @@ if ($institution || $add) {
}
$elements['lockedfieldshelp'] = array(
'value' => '<tr id="lockedfieldshelp"><th colspan="2">'
. get_help_icon('core', 'admin', 'institution', 'lockedfields')
. get_help_icon('core', 'admin', 'institution', 'lockedfields')
. '</th></tr>'
);
......@@ -648,6 +657,7 @@ function institution_submit(Pieform $form, $values) {
}
$newinstitution->theme = (empty($values['theme']) || $values['theme'] == 'sitedefault') ? null : $values['theme'];
$newinstitution->dropdownmenu = ($values['dropdownmenu']) ? 1 : 0;
$newinstitution->skins = ($values['skins']) ? 1 : 0;
if ($newinstitution->theme == 'custom') {
if (!empty($oldinstitution->style)) {
......
......@@ -374,6 +374,8 @@ $string['sitenamedescription'] = 'The site name appears in certain places around
$string['siteoptionspagedescription'] = 'Here you can set some global options that will apply by default throughout the entire site. <BR> Note: Disabled options are overridden by your config.php file.';
$string['siteoptionsset'] = 'Site options have been updated.';
$string['sitethemedescription'] = 'The default theme for the site. If your theme is not listed, check the error log.';
$string['skins'] = 'Page skins';
$string['skinsinstitutiondescription'] = 'Allow this institution\'s users to set "skins" on their Pages.';
$string['smallviewheaders'] = 'Small page headers';
$string['smallviewheadersdescription'] = 'If checked, a small header and site navigation block will be displayed when viewing or editing portfolio pages created by users.';
$string['spamhaus'] = 'Enable Spamhaus URL blacklist';
......
......@@ -536,7 +536,7 @@ $cfg->additionalhtlmfooter = '';
$cfg->usersuniquebyusername = false;
/**
* @global bool $cfg->skins Activates the "page skins" feature, which allows users to customize the CSS
* @global bool $cfg->skins Activates the experimental "page skins" feature, which allows users to customize the CSS
* on individual pages.
*/
// $cfg->skins = false;
\ No newline at end of file
......@@ -80,6 +80,7 @@
<FIELD NAME="licensemandatory" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0"/>
<FIELD NAME="licensedefault" TYPE="char" LENGTH="255" NOTNULL="false"/>
<FIELD NAME="dropdownmenu" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0"/>
<FIELD NAME="skins" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="1"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="name" />
......
......@@ -3355,7 +3355,6 @@ function xmldb_core_upgrade($oldversion=0) {
log_debug("Upgrading pages: $done/$pwcount");
set_time_limit(30);
}
}
if ($oldversion < 2013091900) {
......@@ -3411,5 +3410,13 @@ function xmldb_core_upgrade($oldversion=0) {
install_skins_default();
}
if ($oldversion < 2013091901) {
// Add a "skins" table to institutions to record whether they've enabled skins or not
$table = new XMLDBTable('institution');
$field = new XMLDBField('skins');
$field->setAttributes(XMLDB_TYPE_INTEGER, 1, null, XMLDB_NOTNULL, null, null, null, 1, 'dropdownmenu');
add_field($table, $field);
}
return $status;
}
......@@ -44,10 +44,11 @@ class Institution {
'registerallowed' => 1,
'theme' => 'default',
'defaultmembershipperiod' => 0,
'maxuseraccounts' => null
);
'maxuseraccounts' => null,
'skins' => 1,
);
function __construct($name = null) {
public function __construct($name = null) {
if (is_null($name)) {
return $this;
}
......@@ -57,7 +58,7 @@ class Institution {
}
}
function __get($name) {
public function __get($name) {
if (array_key_exists($name, $this->members)) {
return $this->members[$name];
}
......@@ -72,31 +73,39 @@ class Institution {
if (!is_string($value) || empty($value) || strlen($value) > 255) {
throw new ParamOutOfRangeException("'name' should be a string between 1 and 255 characters in length");
}
} elseif ($name == 'displayname') {
}
else if ($name == 'displayname') {
if (!is_string($value) || empty($value) || strlen($value) > 255) {
throw new ParamOutOfRangeException("'displayname' ($value) should be a string between 1 and 255 characters in length");
}
} elseif ($name == 'registerallowed') {
}
else if ($name == 'registerallowed') {
if (!is_numeric($value) || $value < 0 || $value > 1) {
throw new ParamOutOfRangeException("'registerallowed' should be zero or one");
}
} elseif ($name == 'theme') {
}
else if ($name == 'theme') {
if (!empty($value) && is_string($value) && strlen($value) > 255) {
throw new ParamOutOfRangeException("'theme' ($value) should be less than 255 characters in length");
}
} elseif ($name == 'defaultmembershipperiod') {
}
else if ($name == 'defaultmembershipperiod') {
if (!empty($value) && (!is_numeric($value) || $value < 0 || $value > 9999999999)) {
throw new ParamOutOfRangeException("'defaultmembershipperiod' should be a number between 1 and 9,999,999,999");
}
} elseif ($name == 'maxuseraccounts') {
}
else if ($name == 'maxuseraccounts') {
if (!empty($value) && (!is_numeric($value) || $value < 0 || $value > 9999999999)) {
throw new ParamOutOfRangeException("'maxuseraccounts' should be a number between 1 and 9,999,999,999");
}
}
else if ($name == 'skins') {
$value = (bool) $value;
}
$this->members[$name] = $value;
}
function findByName($name) {
public function findByName($name) {
if (!is_string($name) || strlen($name) < 1 || strlen($name) > 255) {
throw new ParamOutOfRangeException("'name' must be a string.");
......@@ -114,7 +123,7 @@ class Institution {
return $this;
}
function initialise($name, $displayname) {
public function initialise($name, $displayname) {
if (empty($name) || !is_string($name)) {
return false;
}
......@@ -129,7 +138,7 @@ class Institution {
return true;
}
function verifyReady() {
public function verifyReady() {
if (empty($this->members['name']) || !is_string($this->members['name'])) {
return false;
}
......@@ -140,7 +149,7 @@ class Institution {
return true;
}
function commit() {
public function commit() {
if (!$this->verifyReady()) {
throw new SystemException('Commit failed');
}
......@@ -151,6 +160,7 @@ class Institution {
$record->theme = $this->theme;
$record->defaultmembershipperiod = $this->defaultmembershipperiod;
$record->maxuseraccounts = $this->maxuseraccounts;
$record->skins = $this->skins;
if ($this->initialized == self::INITIALIZED) {
return insert_record('institution', $record);
......@@ -168,6 +178,7 @@ class Institution {
$this->theme = $result->theme;
$this->defaultmembershipperiod = $result->defaultmembershipperiod;
$this->maxuseraccounts = $result->maxuseraccounts;
$this->skins = $result->skins;
$this->verifyReady();
}
......
......@@ -1063,6 +1063,67 @@ function set_config_plugin_instance($plugintype, $pluginname, $pluginid, $key, $
return false;
}
/**
* Fetch an institution configuration
* TODO: If needed, create a corresponding set_config_institution()
* @param string $institutionname
* @param string $key
* @return mixed The value of the key or NULL if the key is not valid
*/
function get_config_institution($institutionname, $key) {
require_once(get_config('docroot').'/lib/institution.php');
// Note that this
static $fetchedinst = array();
if (isset($fetchedinst[$institutionname])) {
$inst = $fetchedinst[$institutionname];
}
else {
try {
$inst = new Institution($institutionname);
}
catch (ParamOutOfRangeException $e) {
return null;
}
}
// Use the magical __get() function of the Institution class
return $inst->{$key};
}
/**
* Fetch a config setting for the specified user's institution.
* @param string $key
* @param int $userid (Optional) If not supplied, fetch for the current user's institution
*/
function get_config_user_institution($key, $userid = null) {
global $USER;
if ($userid === null) {
$userid = $USER->id;
}
static $cache = array();
if (isset($cache[$userid][$key])) {
return $cache[$userid][$key];
}
if ($userid == null) {
$institutions = $USER->get('institutions');
}
else {
$institutions = load_user_institutions($userid);
}
// If the user belongs to no institution, check the Mahara institution
if (!$institutions) {
$institutions = get_records_assoc('institution', 'name', 'mahara');
}
$results = array();
foreach ($institutions as $instname => $inst) {
$results[$instname] = get_config_institution($instname, $key);
}
$cache[$userid][$key] = $results;
return $results;
}
/**
* This function prints an array or object
* wrapped inside <pre></pre>
......
......@@ -1221,6 +1221,16 @@ class Skin {
global $USER;
return $this->type == 'public' || $this->type == 'site' || ($this->owner == $USER->get('id'));
}
/**
* Indicates whether or not the current user is allowed to see this skin at all
* @return boolean
*/
public function can_view() {
// TODO: For tighter control of views, it might be good to implement this. It would have to check for whether it's
// public, or whether it's used in a view that you are allowed to look at
return true;
}
}
......@@ -1380,4 +1390,4 @@ function install_skins_default() {
'fontstack' => '\'Verdana\', \'DejaVu Sans\'',
'genericfont' => 'sans-serif'
));
}
\ No newline at end of file
}
......@@ -1541,7 +1541,7 @@ function load_user_institutions($userid) {
throw new InvalidArgumentException("couldn't load institutions, no user id specified");
}
if ($institutions = get_records_sql_assoc('
SELECT u.institution,'.db_format_tsfield('ctime').','.db_format_tsfield('u.expiry', 'membership_expiry').',u.studentid,u.staff,u.admin,i.displayname,i.theme,i.registerallowed, i.showonlineusers,i.allowinstitutionpublicviews, i.logo, i.style, i.licensemandatory, i.licensedefault, i.dropdownmenu
SELECT u.institution,'.db_format_tsfield('ctime').','.db_format_tsfield('u.expiry', 'membership_expiry').',u.studentid,u.staff,u.admin,i.displayname,i.theme,i.registerallowed, i.showonlineusers,i.allowinstitutionpublicviews, i.logo, i.style, i.licensemandatory, i.licensedefault, i.dropdownmenu, i.skins
FROM {usr_institution} u INNER JOIN {institution} i ON u.institution = i.name
WHERE u.usr = ? ORDER BY i.priority DESC', array($userid))) {
return $institutions;
......
......@@ -31,7 +31,7 @@ $config = new stdClass();
// See https://wiki.mahara.org/index.php/Developer_Area/Version_Numbering_Policy
// For upgrades on stable branches, increment the version by one. On master, use the date.
$config->version = 2013091900;
$config->version = 2013091901;
$config->release = '1.8.0dev';
$config->minupgradefrom = 2008040200;
$config->minupgraderelease = '1.0.0 (release tag 1.0.0_RELEASE)';
......
......@@ -2364,12 +2364,6 @@ function mahara_standard_nav() {
'title' => get_string('sharedwithme', 'view'),
'weight' => 60,
),
'myportfolio/skins' => array(
'path' => 'myportfolio/skins',
'url' => 'skin/index.php',
'title' => get_string('myskins', 'skin'),
'weight' => 65,
),
'myportfolio/export' => array(
'path' => 'myportfolio/export',
'url' => 'export/index.php',
......@@ -2422,6 +2416,14 @@ function mahara_standard_nav() {
),
);
if (can_use_skins()) {
$menu['myportfolio/skins'] = array(
'path' => 'myportfolio/skins',
'url' => 'skin/',
'title' => get_string('myskins', 'skin'),
'weight' => 65,
);
}
return $menu;
}
......@@ -3853,4 +3855,26 @@ function escape_css_string($string, $singlequote=true) {
array('\\\\', '', "\\$delim"),
$string
);
}
\ No newline at end of file
}
/**
* Indicates whether a particular user can use skins on their pages or not. This is in
* lib/web.php instead of lib/skin.php so that we can use it while generating the main nav.
* @param int $userid The Id of the user to check. Null checks the current user.
* @return bool
*/
function can_use_skins($userid = null) {
if (!get_config('skins')) {
return false;
}
// A user can belong to multiple institutions. If any of their institutions allow it, then
// let them use skins!
$results = get_config_user_institution('skins', $userid);
foreach ($results as $r) {
if ($r) {
return true;
}
}
return false;
}
......@@ -30,7 +30,7 @@ require(dirname(dirname(__FILE__)) . '/init.php');
require_once('skin.php');
require_once('pieforms/pieform.php');
if (!get_config('skins')) {
if (!can_use_skins()) {
throw new FeatureNotEnabledException();
}
......
......@@ -35,7 +35,7 @@ require_once('skin.php');
require_once('pieforms/pieform.php');
safe_require('artefact', 'file');
if (!get_config('skins')) {
if (!can_use_skins()) {
throw new FeatureNotEnabledException();
}
......
......@@ -30,7 +30,7 @@ require_once(dirname(dirname(__FILE__)) . '/init.php');
require_once('skin.php');
require_once(get_config('docroot') . 'artefact/file/lib.php');
if (!get_config('skins')) {
if (!can_use_skins()) {
throw new FeatureNotEnabledException();
}
......@@ -69,7 +69,11 @@ $topnode = $xmldoc->appendChild($topelement);
if (!empty($exportskins)) {
foreach ($exportskins as $exportskin) {
$skinobj = new Skin($exportskin->id);
// Only allow a user to export skins they have edit permissions for
if (!$skinobj->can_edit()) {
continue;
}
$viewskin = unserialize($exportskin->viewskin);
$rootelement = $xmldoc->createElement('skin');
......@@ -155,24 +159,26 @@ if (!empty($exportskins)) {
if (!empty($bodybg) && $bodybg > 0) {
// Get existing skin background image data...
$artefactobj = new ArtefactTypeImage($bodybg);
$artefact = get_record('artefact', 'id', $bodybg, null, null, null, null, 'artefacttype,title,description,note');
$artefactfilefiles = get_record('artefact_file_files', 'artefact', $bodybg);
$artefactfileimage = get_record('artefact_file_image', 'artefact', $bodybg);
if ($USER->can_view_artefact($artefactobj)) {
$artefact = get_record('artefact', 'id', $bodybg, null, null, null, null, 'artefacttype,title,description,note');
$artefactfilefiles = get_record('artefact_file_files', 'artefact', $bodybg);
$artefactfileimage = get_record('artefact_file_image', 'artefact', $bodybg);
// Open and read the contents of each file...
$bodybgimage = $artefactobj->get_path();
$fp = fopen($bodybgimage, 'rb');
$filesize = filesize($bodybgimage);
$contents = fread($fp, $filesize);
fclose($fp);
// Export each file...
$childelement = $xmldoc->createElement('image');
$itemnode = $rootelement->appendChild($childelement);
$itemnode->setAttribute('type', 'body-background-image');
$itemnode->setAttribute('artefact', serialize($artefact));
$itemnode->setAttribute('artefact_file_files', serialize($artefactfilefiles));
$itemnode->setAttribute('artefact_file_image', serialize($artefactfileimage));
$itemnode->setAttribute('contents', base64_encode($contents));
// Open and read the contents of each file...
$bodybgimage = $artefactobj->get_path();
$fp = fopen($bodybgimage, 'rb');
$filesize = filesize($bodybgimage);
$contents = fread($fp, $filesize);
fclose($fp);
// Export each file...
$childelement = $xmldoc->createElement('image');
$itemnode = $rootelement->appendChild($childelement);
$itemnode->setAttribute('type', 'body-background-image');
$itemnode->setAttribute('artefact', serialize($artefact));
$itemnode->setAttribute('artefact_file_files', serialize($artefactfilefiles));
$itemnode->setAttribute('artefact_file_image', serialize($artefactfileimage));
$itemnode->setAttribute('contents', base64_encode($contents));
}
}
// Page background image element...
......@@ -181,23 +187,25 @@ if (!empty($exportskins)) {
// Get existing page background image data...
// Get existing skin background image data...
$artefactobj = new ArtefactTypeImage($viewbg);
$artefact = get_record('artefact', 'id', $viewbg, null, null, null, null, 'artefacttype,title,description,note');
$artefactfilefiles = get_record('artefact_file_files', 'artefact', $viewbg);
$artefactfileimage = get_record('artefact_file_image', 'artefact', $viewbg);
// Open and read the contents of each file...
$viewbgimage = $artefactobj->get_path();
$fp = fopen($viewbgimage, 'rb');
$filesize = filesize($viewbgimage);
$contents = fread($fp, $filesize);
fclose($fp);
// Export each file...
$childelement = $xmldoc->createElement('image');
$itemnode = $rootelement->appendChild($childelement);
$itemnode->setAttribute('type', 'view-background-image');
$itemnode->setAttribute('artefact', serialize($artefact));
$itemnode->setAttribute('artefact_file_files', serialize($artefactfilefiles));
$itemnode->setAttribute('artefact_file_image', serialize($artefactfileimage));
$itemnode->setAttribute('contents', base64_encode($contents));
if ($USER->can_view_artefact($artefactobj)) {
$artefact = get_record('artefact', 'id', $viewbg, null, null, null, null, 'artefacttype,title,description,note');
$artefactfilefiles = get_record('artefact_file_files', 'artefact', $viewbg);
$artefactfileimage = get_record('artefact_file_image', 'artefact', $viewbg);
// Open and read the contents of each file...
$viewbgimage = $artefactobj->get_path();
$fp = fopen($viewbgimage, 'rb');
$filesize = filesize($viewbgimage);
$contents = fread($fp, $filesize);
fclose($fp);
// Export each file...
$childelement = $xmldoc->createElement('image');
$itemnode = $rootelement->appendChild($childelement);
$itemnode->setAttribute('type', 'view-background-image');
$itemnode->setAttribute('artefact', serialize($artefact));
$itemnode->setAttribute('artefact_file_files', serialize($artefactfilefiles));
$itemnode->setAttribute('artefact_file_image', serialize($artefactfileimage));
$itemnode->setAttribute('contents', base64_encode($contents));
}
}
// Fonts element...
......
......@@ -29,7 +29,7 @@ define('INTERNAL', true);
require_once(dirname(dirname(__FILE__)) . '/init.php');
require_once('skin.php');
if (!get_config('skins')) {
if (!can_use_skins()) {
throw new FeatureNotEnabledException();
}
......
......@@ -37,7 +37,7 @@ require_once('file.php');
require_once('uploadmanager.php');
define('TITLE', get_string('importskins', 'skin'));
if (!get_config('skins')) {
if (!can_use_skins()) {
throw new FeatureNotEnabledException();
}
......
......@@ -36,7 +36,7 @@ require_once('skin.php');
require_once('pieforms/pieform.php');
define('TITLE', get_string('myskins', 'skin'));
if (!get_config('skins')) {
if (!can_use_skins()) {
throw new FeatureNotEnabledException();
}
......
......@@ -44,6 +44,10 @@ if ($id == 0) {
$viewid = param_integer('view', null);
$skin = get_record('skin', 'id', $id);
$skinobj = new Skin($id);
if (!$skinobj->can_view()) {
throw new AccessDeniedException();
}
$skin->viewskin = unserialize($skin->viewskin);
// Set no caching for thumbnails...
......
......@@ -29,12 +29,17 @@ define('INTERNAL', 1);
define('PUBLIC', 1);
define('NOCHECKPASSWORDCHANGE', 1);
require(dirname(dirname(__FILE__)) . '/init.php');
require_once(get_config('docroot') . '/lib/skin.php');
if (!get_config('skins')) {
throw new FeatureNotEnabledException();
}
$id = param_integer('id', 0);
$skinobj = new Skin($id);
if (!$skinobj->can_use()) {
throw new AccessDeniedException();
}
//Set no caching for thumbnails...
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
......
......@@ -3,7 +3,7 @@
{if $edittitle}<li {if $selected == 'title'} class="current-tab"{/if}><a{if $selected == 'title'} class="current-tab"{/if} href="{$WWWROOT}view/edit.php?id={$viewid}{if $new}&new=1{/if}">{str tag=edittitleanddescription section=view}</a></li>{/if}
<li {if $selected == 'layout'} class="current-tab"{/if}><a{if $selected == 'layout'} class="current-tab"{/if} href="{$WWWROOT}view/layout.php?id={$viewid}{if $new}&new=1{/if}">{str tag=editlayout section=view}</a></li>
<li {if $selected == 'content'} class="current-tab"{/if}><a{if $selected == 'content'} class="current-tab"{/if} href="{$WWWROOT}view/blocks.php?id={$viewid}{if $new}&new=1{/if}">{str tag=editcontent section=view}</a></li>
{ifconfig key=skins}<li {if $selected == 'skin'} class="current-tab"{/if}><a{if $selected == 'skin'} class="current-tab"{/if} href="{$WWWROOT}view/skin.php?id={$viewid}{if $new}&new=1{/if}">{str tag=chooseskin section=skin}</a></li>{/ifconfig}
{if can_use_skins()}<li {if $selected == 'skin'} class="current-tab"{/if}><a{if $selected == 'skin'} class="current-tab"{/if} href="{$WWWROOT}view/skin.php?id={$viewid}{if $new}&new=1{/if}">{str tag=chooseskin section=skin}</a></li>{/if}
<li class="displaypage"><a href="{$displaylink}">{str tag=displayview section=view} &raquo;</a></li>
{if $edittitle || $viewtype == 'profile'}<li class="sharepage"><a href="{$WWWROOT}view/access.php?id={$viewid}{if $new}&new=1{/if}">{str tag=shareview section=view} &raquo;</a></li>{/if}
</ul></div>
......@@ -3,7 +3,8 @@
{if $edittitle}<li {if $selected == 'title'} class="current-tab"{/if}><a{if $selected == 'title'} class="current-tab"{/if} href="{$WWWROOT}view/edit.php?id={$viewid}{if $new}&new=1{/if}">{str tag=edittitleanddescription section=view}</a></li>{/if}
<li {if $selected == 'layout'} class="current-tab"{/if}><a{if $selected == 'layout'} class="current-tab"{/if} href="{$WWWROOT}view/layout.php?id={$viewid}{if $new}&new=1{/if}">{str tag=editlayout section=view}</a></li>
<li {if $selected == 'content'} class="current-tab"{/if}><a{if $selected == 'content'} class="current-tab"{/if} href="{$WWWROOT}view/blocks.php?id={$viewid}{if $new}&new=1{/if}">{str tag=editcontent section=view}</a></li>
{ifconfig key=skins}<li {if $selected == 'skin'} class="current-tab"{/if}><a{if $selected == 'skin'} class="current-tab"{/if} href="{$WWWROOT}view/skin.php?id={$viewid}{if $new}&new=1{/if}">{str tag=chooseskin section=skin}</a></li>{/ifconfig}
<li>HEY</li>
{if can_use_skins}<li {if $selected == 'skin'} class="current-tab"{/if}><a{if $selected == 'skin'} class="current-tab"{/if} href="{$WWWROOT}view/skin.php?id={$viewid}{if $new}&new=1{/if}">{str tag=chooseskin section=skin}</a></li>{/ifconfig}
<li class="displaypage"><a href="{$displaylink}">{str tag=displayview section=view} &raquo;</a></li>
{if $edittitle || $viewtype == 'profile'}<li class="sharepage"><a href="{$WWWROOT}view/access.php?id={$viewid}{if $new}&new=1{/if}">{str tag=shareview section=view} &raquo;</a></li>{/if}
</ul></div>
......@@ -33,13 +33,12 @@ require_once('view.php');
require_once(get_config('libroot') . 'group.php');
define('TITLE', get_string('chooseviewskin', 'skin'));
if (!get_config('skins')) {
throw new FeatureNotEnabledException();
}
$id = param_integer('id');
$new = param_boolean('new');
$view = new View($id);
if (!can_use_skins()) {
throw new FeatureNotEnabledException();
}
$view->set_edit_nav();