Merged changes for MDL-25394

This commit is contained in:
Sam Hemelryk
2011-06-08 10:58:42 +08:00
12 changed files with 575 additions and 113 deletions
+2
View File
@@ -18,6 +18,8 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
$temp->add(new admin_setting_configcheckbox('allowuserblockhiding', get_string('allowuserblockhiding', 'admin'), get_string('configallowuserblockhiding', 'admin'), 1));
$temp->add(new admin_setting_configcheckbox('allowblockstodock', get_string('allowblockstodock', 'admin'), get_string('configallowblockstodock', 'admin'), 1));
$temp->add(new admin_setting_configtextarea('custommenuitems', get_string('custommenuitems', 'admin'), get_string('configcustommenuitems', 'admin'), '', PARAM_TEXT, '50', '10'));
$temp->add(new admin_setting_configcheckbox('enabledevicedetection', get_string('enabledevicedetection', 'admin'), get_string('configenabledevicedetection', 'admin'), 1));
$temp->add(new admin_setting_devicedetectregex('devicedetectregex', get_string('devicedetectregex', 'admin'), get_string('devicedetectregex_desc', 'admin'), ''));
$ADMIN->add('themes', $temp);
$ADMIN->add('themes', new admin_externalpage('themeselector', get_string('themeselector','admin'), $CFG->wwwroot . '/theme/index.php'));
+10
View File
@@ -187,6 +187,7 @@ $string['configdefaultuserroleid'] = 'All logged in users will be given the capa
$string['configdeleteincompleteusers'] = 'After this period, old not fully setup accounts are deleted.';
$string['configdeleteunconfirmed'] = 'If you are using email authentication, this is the period within which a response will be accepted from users. After this period, old unconfirmed accounts are deleted.';
$string['configdenyemailaddresses'] = 'To deny email addresses from particular domains list them here in the same way. All other domains will be accepted. To deny subdomains add the domain with a preceding \'.\'. eg <strong>hotmail.com yahoo.co.uk .live.com</strong>';
$string['configenabledevicedetection'] = 'Enables detection of mobiles, smartphones, tablets or default devices (desktop PCs, laptops, etc) for the application of themes and other features.';
$string['configdigestmailtime'] = 'People who choose to have emails sent to them in digest form will be emailed the digest daily. This setting controls which time of day the daily mail will be sent (the next cron that runs after this hour will send it).';
$string['configdisableuserimages'] = 'Disable the ability for users to change user profile images.';
$string['configdisplayloginfailures'] = 'This will display information to selected users about previous failed logins.';
@@ -450,6 +451,12 @@ $string['deletingqtype'] = 'Deleting question type \'{$a}\'';
$string['density'] = 'Density';
$string['denyemailaddresses'] = 'Denied email domains';
$string['development'] = 'Development';
$string['devicedetectregex'] = 'Device detection regular expressions';
$string['devicedetectregex_desc'] = '<p>By default, Moodle can detect devices of the type default (desktop PCs, laptops, etc), mobile (phones and small hand held devices), tablet (iPads, Android tablets) and legacy (Internet Explorer 6 users). The theme selector can be used to apply separate themes to all of these. This setting allows regular expressions that allow the detection of extra device types (these take precedence over the default types).</p>
<p>For example, you could enter the regular expression \'/(MIDP-1.0|Maemo|Windows CE)/\' to detect some commonly used feasture phones add the return value \'featurephone\'. This adds \'featurephone\' on the theme selector that would allow you to add a theme that would be used on these devices. Other phones would still use the theme selected for the mobile device type.</p>';
$string['devicedetectregexexpression'] = 'Regular expression';
$string['devicedetectregexvalue'] = 'Return value';
$string['devicetype'] = 'Device type';
$string['digestmailtime'] = 'Hour to send digest emails';
$string['disableuserimages'] = 'Disable user profile images';
$string['displayerrorswarning'] = 'Enabling the PHP setting <em>display_errors</em> is not recommended on production sites because some error messages may reveal sensitive information about your server.';
@@ -491,6 +498,7 @@ $string['enablecomments'] = 'Enable comments';
$string['enablecourseajax'] = 'Enable AJAX course editing';
$string['enablecourseajax_desc'] = 'Allow AJAX when editing main course pages. Note that the course format and the theme must support AJAX editing and the user has to enable AJAX in their profiles, too.';
$string['enablecourserequests'] = 'Enable course requests';
$string['enabledevicedetection'] = 'Enable device detection';
$string['enableglobalsearch'] = 'Enable global search';
$string['enablegroupmembersonly'] = 'Enable group members only';
$string['enablehtmlpurifier'] = 'Enable HTML Purifier';
@@ -993,7 +1001,9 @@ $string['tabselectedtofront'] = 'On tables with tabs, should the row with the cu
$string['tabselectedtofronttext'] = 'Bring selected tab row to front';
$string['themedesignermode'] = 'Theme designer mode';
$string['themelist'] = 'Theme list';
$string['themenoselected'] = 'No theme selected';
$string['themeresetcaches'] = 'Clear theme caches';
$string['themeselect'] = 'Select theme';
$string['themeselector'] = 'Theme selector';
$string['themesettings'] = 'Theme settings';
$string['therewereerrors'] = 'There were errors in your data';
+1
View File
@@ -277,6 +277,7 @@ $string['invalidcoursemodule'] = 'Invalid course module ID';
$string['invalidcoursenameshort'] = 'Invalid short course name';
$string['invaliddata'] = 'Data submitted is invalid';
$string['invaliddatarootpermissions'] = 'Invalid permissions detected in $CFG->dataroot directory, administrator has to fix permissions.';
$string['invaliddevicetype'] = 'Invalid device type';
$string['invalidelementid'] = 'Incorrect element id!';
$string['invalidentry'] = 'This is not valid entry!';
$string['invalidevent'] = 'Invalid event';
+3 -3
View File
@@ -906,7 +906,6 @@ $string['latestlanguagepack'] = 'Check for latest language pack on moodle.org';
$string['layouttable'] = 'Layout table';
$string['leavetokeep'] = 'Leave blank to keep current password';
$string['legacythemeinuse'] = 'This site is being displayed to you in compatibility mode because your browser is too old.';
$string['legacythemesaved'] = 'New legacy theme saved';
$string['license'] = 'Licence';
$string['licenses'] = 'Licences';
$string['liketologin'] = 'Would you like to log in now with a full user account?';
@@ -1603,6 +1602,8 @@ $string['summary'] = 'Summary';
$string['summary_help'] = 'The idea of a summary is a short text to prepare students for the activities within the topic or week. The text is shown on the course page under the section name.';
$string['summaryof'] = 'Summary of {$a}';
$string['supplyinfo'] = 'More details';
$string['switchdevicedefault'] = 'Switch to the standard theme';
$string['switchdevicerecommended'] = 'Switch to the recommended theme for your device';
$string['switchrolereturn'] = 'Return to my normal role';
$string['switchroleto'] = 'Switch role to...';
$string['tag'] = 'Tag';
@@ -1692,8 +1693,6 @@ $string['uploadthisfile'] = 'Upload this file';
$string['url'] = 'URL';
$string['used'] = 'Used';
$string['usedinnplaces'] = 'Used in {$a} places';
$string['useformaintheme'] = 'Use for modern browsers';
$string['useforlegacytheme'] = 'Use for old browsers';
$string['usemessageform'] = 'or use the form below to send a message to the selected students';
$string['user'] = 'User';
$string['userconfirmed'] = 'Confirmed {$a}';
@@ -1723,6 +1722,7 @@ $string['userswithfiles'] = 'Users with files';
$string['useruploadtype'] = 'User upload type: {$a}';
$string['userviewingsettings'] = 'Profile settings for {$a}';
$string['userzones'] = 'User zones';
$string['usetheme'] = 'Use theme';
$string['usingexistingcourse'] = 'Using existing course';
$string['valuealreadyused'] = 'This value has already been used.';
$string['version'] = 'Version';
+191 -1
View File
@@ -7335,9 +7335,199 @@ class admin_setting_configcolourpicker extends admin_setting {
$content .= html_writer::end_tag('div');
return format_admin_setting($this, $this->visiblename, $content, $this->description, false, '', $this->get_defaultsetting(), $query);
}
}
/**
* Administration interface for user specified regular expressions for device detection.
*
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class admin_setting_devicedetectregex extends admin_setting {
/**
* Calls parent::__construct with specific args
*
* @param string $name
* @param string $visiblename
* @param string $description
* @param mixed $defaultsetting
*/
public function __construct($name, $visiblename, $description, $defaultsetting = '') {
global $CFG;
parent::__construct($name, $visiblename, $description, $defaultsetting);
}
/**
* Return the current setting(s)
*
* @return array Current settings array
*/
public function get_setting() {
global $CFG;
$config = $this->config_read($this->name);
if (is_null($config)) {
return null;
}
return $this->prepare_form_data($config);
}
/**
* Save selected settings
*
* @param array $data Array of settings to save
* @return bool
*/
public function write_setting($data) {
if (empty($data)) {
$data = array();
}
if ($this->config_write($this->name, $this->process_form_data($data))) {
return ''; // success
} else {
return get_string('errorsetting', 'admin') . $this->visiblename . html_writer::empty_tag('br');
}
}
/**
* Return XHTML field(s) for regexes
*
* @param array $data Array of options to set in HTML
* @return string XHTML string for the fields and wrapping div(s)
*/
public function output_html($data, $query='') {
global $OUTPUT;
$out = html_writer::start_tag('table', array('border' => 1, 'class' => 'generaltable'));
$out .= html_writer::start_tag('thead');
$out .= html_writer::start_tag('tr');
$out .= html_writer::tag('th', get_string('devicedetectregexexpression', 'admin'));
$out .= html_writer::tag('th', get_string('devicedetectregexvalue', 'admin'));
$out .= html_writer::end_tag('tr');
$out .= html_writer::end_tag('thead');
$out .= html_writer::start_tag('tbody');
if (empty($data)) {
$looplimit = 1;
} else {
$looplimit = (count($data)/2)+1;
}
for ($i=0; $i<$looplimit; $i++) {
$out .= html_writer::start_tag('tr');
$expressionname = 'expression'.$i;
if (!empty($data[$expressionname])){
$expression = $data[$expressionname];
} else {
$expression = '';
}
$out .= html_writer::tag('td',
html_writer::empty_tag('input',
array(
'type' => 'text',
'class' => 'form-text',
'name' => $this->get_full_name().'[expression'.$i.']',
'value' => $expression,
)
), array('class' => 'c'.$i)
);
$valuename = 'value'.$i;
if (!empty($data[$valuename])){
$value = $data[$valuename];
} else {
$value= '';
}
$out .= html_writer::tag('td',
html_writer::empty_tag('input',
array(
'type' => 'text',
'class' => 'form-text',
'name' => $this->get_full_name().'[value'.$i.']',
'value' => $value,
)
), array('class' => 'c'.$i)
);
$out .= html_writer::end_tag('tr');
}
$out .= html_writer::end_tag('tbody');
$out .= html_writer::end_tag('table');
return format_admin_setting($this, $this->visiblename, $out, $this->description, false, '', null, $query);
}
/**
* Converts the string of regexes
*
* @see self::process_form_data()
* @param $regexes string of regexes
* @return array of form fields and their values
*/
protected function prepare_form_data($regexes) {
$regexes = json_decode($regexes);
$form = array();
$i = 0;
foreach ($regexes as $value => $regex) {
$expressionname = 'expression'.$i;
$valuename = 'value'.$i;
$form[$expressionname] = $regex;
$form[$valuename] = $value;
$i++;
}
return $form;
}
/**
* Converts the data from admin settings form into a string of regexes
*
* @see self::prepare_form_data()
* @param array $data array of admin form fields and values
* @return false|string of regexes
*/
protected function process_form_data(array $form) {
$count = count($form); // number of form field values
if ($count % 2) {
// we must get five fields per expression
return false;
}
$regexes = array();
for ($i = 0; $i < $count / 2; $i++) {
$expressionname = "expression".$i;
$valuename = "value".$i;
$expression = trim($form['expression'.$i]);
$value = trim($form['value'.$i]);
if (empty($expression)){
continue;
}
$regexes[$value] = $expression;
}
$regexes = json_encode($regexes);
return $regexes;
}
}
/**
* Multiselect for current modules
+1 -1
View File
@@ -6521,4 +6521,4 @@ WHERE gradeitemid IS NOT NULL AND grademax IS NOT NULL");
// 1/ drop block_pinned_old table here and in install.xml
// 2/ drop block_instance_old table here and in install.xml
//TODO: AFTER 2.0 remove the column user->emailstop and the user preference "message_showmessagewindow"
//TODO: AFTER 2.0 remove the column user->emailstop and the user preference "message_showmessagewindow"
+137
View File
@@ -7604,6 +7604,143 @@ function check_php_version($version='5.2.4') {
return false;
}
/**
* Returns whether a device/browser combination is mobile, tablet, legacy, default or the result of
* an optional admin specified regular expression. If enabledevicedetection is set to no or not set
* it returns default
*
* @return string device type
*/
function get_device_type() {
global $CFG;
if (empty($CFG->enabledevicedetection) || empty($_SERVER['HTTP_USER_AGENT'])) {
return 'default';
}
$useragent = $_SERVER['HTTP_USER_AGENT'];
if (!empty($CFG->devicedetectregex)) {
$regexes = json_decode($CFG->devicedetectregex);
foreach ($regexes as $value=>$regex) {
if (preg_match($regex, $useragent)) {
return $value;
}
}
}
//mobile detection PHP direct copy from open source detectmobilebrowser.com
$phonesregex = '/android|avantgo|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i';
$modelsregex = '/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-/i';
if (preg_match($phonesregex,$useragent) || preg_match($modelsregex,substr($useragent, 0, 4))){
return 'mobile';
}
$tabletregex = '/Tablet browser|iPad|iProd|GT-P1000|GT-I9000|SHW-M180S|SGH-T849|SCH-I800|Build\/ERE27|sholest/i';
if (preg_match($tabletregex, $useragent)) {
return 'tablet';
}
if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 6.') !== false) {
return 'legacy';
}
return 'default';
}
/**
* Returns a list of the device types supporting by Moodle
*
* @param boolean $incusertypes includes types specified using the devicedetectregex admin setting
* @return array $types
*/
function get_device_type_list($incusertypes = true) {
global $CFG;
$types = array('default', 'legacy', 'mobile', 'tablet');
if ($incusertypes && !empty($CFG->devicedetectregex)) {
$regexes = json_decode($CFG->devicedetectregex);
foreach ($regexes as $value => $regex) {
$types[] = $value;
}
}
return $types;
}
/**
* Returns the theme selected for a particular device or false if none selected.
*
* @param string $devicetype
* @return string|false The name of the theme to use for the device or the false if not set
*/
function get_selected_theme_for_device_type($devicetype = null) {
global $CFG;
if (empty($devicetype)) {
$devicetype = get_user_device_type();
}
$themevarname = get_device_cfg_var_name($devicetype);
if (empty($CFG->$themevarname)) {
return false;
}
return $CFG->$themevarname;
}
/**
* Returns the name of the device type theme var in $CFG (because there is not a standard convention to allow backwards compatability
*
* @param string $devicetype
* @return string The config variable to use to determine the theme
*/
function get_device_cfg_var_name($devicetype = null) {
if ($devicetype == 'default' || empty($devicetype)) {
return 'theme';
}
return 'theme' . $devicetype;
}
/**
* Allows the user to switch the device they are seeing the theme for.
* This allows mobile users to switch back to the default theme, or theme for any other device.
*
* @param string $newdevice The device the user is currently using.
* @return string The device the user has switched to
*/
function set_user_device_type($newdevice) {
global $USER;
$devicetype = get_device_type();
$devicetypes = get_device_type_list();
if ($newdevice == $devicetype) {
unset_user_preference('switchdevice'.$devicetype);
} else if (in_array($newdevice, $devicetypes)) {
set_user_preference('switchdevice'.$devicetype, $newdevice);
}
}
/**
* Returns the device the user is currently using, or if the user has chosen to switch devices
* for the current device type the type they have switched to.
*
* @return string The device the user is currently using or wishes to use
*/
function get_user_device_type() {
$device = get_device_type();
$switched = get_user_preferences('switchdevice'.$device, false);
if ($switched != false) {
return $switched;
}
return $device;
}
/**
* Returns one or several CSS class names that match the user's browser. These can be put
* in the body tag of the page to apply browser-specific rules without relying on CSS hacks
+38 -2
View File
@@ -362,10 +362,14 @@ class core_renderer extends renderer_base {
// but some of the content won't be known until later, so we return a placeholder
// for now. This will be replaced with the real content in {@link footer()}.
$output = self::PERFORMANCE_INFO_TOKEN;
if ($this->page->legacythemeinuse) {
if ($this->page->devicetypeinuse == 'legacy') {
// The legacy theme is in use print the notification
$output .= html_writer::tag('div', get_string('legacythemeinuse'), array('class'=>'legacythemeinuse'));
}
// Get links to switch device types (only shown for users not on a default device)
$output .= $this->theme_switch_links();
if (!empty($CFG->debugpageinfo)) {
$output .= '<div class="performanceinfo pageinfo">This page is: ' . $this->page->debug_summary() . '</div>';
}
@@ -2496,8 +2500,40 @@ EOD;
// Return the sub menu
return $content;
}
}
/**
* Renders theme links for switching between default and other themes.
*
* @return string
*/
protected function theme_switch_links() {
$actualdevice = get_device_type();
$currentdevice = $this->page->devicetypeinuse;
$switched = ($actualdevice != $currentdevice);
if (!$switched && $currentdevice == 'default' && $actualdevice == 'default') {
// The user is using the a default device and hasn't switched so don't shown the switch
// device links.
return '';
}
if ($switched) {
$linktext = get_string('switchdevicerecommended');
$devicetype = $actualdevice;
} else {
$linktext = get_string('switchdevicedefault');
$devicetype = 'default';
}
$linkurl = new moodle_url('/theme/switchdevice.php', array('url' => $this->page->url, 'device' => $devicetype, 'sesskey' => sesskey()));
$content = html_writer::start_tag('div', array('id' => 'theme_switch_link'));
$content .= html_writer::link($linkurl, $linktext);
$content .= html_writer::end_tag('div');
return $content;
}
}
/// RENDERERS
+39 -34
View File
@@ -64,13 +64,13 @@ defined('MOODLE_INTERNAL') || die();
* @property-read object $course The current course that we are inside - a row from the
* course table. (Also available as $COURSE global.) If we are not inside
* an actual course, this will be the site course.
* @property-read string $devicetypeinuse The name of the device type in use
* @property-read string $docspath The path to the Moodle docs for this page.
* @property-read string $focuscontrol The id of the HTML element to be focused when the page has loaded.
* @property-read bool $headerprinted
* @property-read string $heading The main heading that should be displayed at the top of the <body>.
* @property-read string $headingmenu The menu (or actions) to display in the heading
* @property-read array $layout_options Returns arrays with options for layout file.
* @property-read bool $legacythemeinuse Returns true if the legacy theme is being used.
* @property-read navbar $navbar Returns the navbar object used to display the navbar
* @property-read global_navigation $navigation Returns the global navigation structure
* @property-read xml_container_stack $opencontainers Tracks XHTML tags on this page that have been opened but not closed.
@@ -217,10 +217,12 @@ class moodle_page {
protected $_legacybrowsers = array('MSIE' => 6.0);
/**
* Is set to true if the chosen legacy theme is in use. False by default.
* @var bool
* Is set to the name of the device type in use.
* This will we worked out when it is first used.
*
* @var string
*/
protected $_legacythemeinuse = false;
protected $_devicetypeinuse = null;
protected $_https_login_required = false;
@@ -522,12 +524,26 @@ class moodle_page {
return $this->_theme;
}
/**
* Please do not call this method directly, use the ->devicetypeinuse syntax. {@link __get()}.
*
* @return string The device type being used.
*/
protected function magic_get_devicetypeinuse() {
if (empty($this->_devicetypeinuse)) {
$this->_devicetypeinuse = get_user_device_type();
}
return $this->_devicetypeinuse;
}
/**
* Please do not call this method directly, use the ->legacythemeinuse syntax. {@link __get()}.
* @deprecated since 2.1
* @return bool
*/
protected function magic_get_legacythemeinuse() {
return ($this->_legacythemeinuse);
debugging('$PAGE->legacythemeinuse is a deprecated property - please use $PAGE->devicetypeinuse and check if it is equal to legacy.', DEVELOPER_DEBUG);
return ($this->devicetypeinuse == 'legacy');
}
/**
@@ -1280,16 +1296,15 @@ class moodle_page {
}
}
$theme = '';
foreach ($themeorder as $themetype) {
switch ($themetype) {
case 'course':
if (!empty($CFG->allowcoursethemes) and !empty($this->course->theme)) {
return $this->course->theme;
if (!empty($CFG->allowcoursethemes) && !empty($this->_course->theme) && $this->devicetypeinuse == 'default') {
return $this->_course->theme;
}
case 'category':
if (!empty($CFG->allowcategorythemes)) {
if (!empty($CFG->allowcategorythemes) && $this->devicetypeinuse == 'default') {
$categories = $this->categories;
foreach ($categories as $category) {
if (!empty($category->theme)) {
@@ -1304,7 +1319,7 @@ class moodle_page {
}
case 'user':
if (!empty($CFG->allowuserthemes) and !empty($USER->theme)) {
if (!empty($CFG->allowuserthemes) && !empty($USER->theme) && $this->devicetypeinuse == 'default') {
if ($mnetpeertheme) {
return $mnetpeertheme;
} else {
@@ -1315,33 +1330,23 @@ class moodle_page {
case 'site':
if ($mnetpeertheme) {
return $mnetpeertheme;
} else if(!empty($CFG->themelegacy) && $this->browser_is_outdated()) {
$this->_legacythemeinuse = true;
return $CFG->themelegacy;
} else {
return $CFG->theme;
}
// First try for the device the user is using.
$devicetheme = get_selected_theme_for_device_type($this->devicetypeinuse);
if (!empty($devicetheme)) {
return $devicetheme;
}
// Next try for the default device (as a fallback)
$devicetheme = get_selected_theme_for_device_type('default');
if (!empty($devicetheme)) {
return $devicetheme;
}
// The default device theme isn't set up - use the overall default theme.
return theme_config::DEFAULT_THEME;
}
}
}
/**
* Determines whether the current browser should
* default to the admin-selected legacy theme
*
* @return true if legacy theme should be used, otherwise false
*
*/
protected function browser_is_outdated() {
foreach($this->_legacybrowsers as $browser => $version) {
// Check the browser is valid first then that its version is suitable
if(check_browser_version($browser, '0') &&
!check_browser_version($browser, $version)) {
return true;
}
}
return false;
}
/**
* Sets ->pagetype from the script name. For example, if the script that was
@@ -1448,8 +1453,8 @@ class moodle_page {
$this->add_body_class('drag');
}
if ($this->_legacythemeinuse) {
$this->add_body_class('legacytheme');
if ($this->_devicetypeinuse != 'default') {
$this->add_body_class($this->_devicetypeinuse . 'theme');
}
}
+119 -71
View File
@@ -23,29 +23,32 @@ require_once(dirname(__FILE__) . '/../config.php');
require_once($CFG->libdir . '/adminlib.php');
$choose = optional_param('choose', '', PARAM_SAFEDIR);
$chooselegacy = optional_param('chooselegacy', '', PARAM_SAFEDIR);
$reset = optional_param('reset', 0, PARAM_BOOL);
$device = optional_param('device', '', PARAM_TEXT);
admin_externalpage_setup('themeselector');
if (!empty($device)) {
// Make sure the device requested is valid
$devices = get_device_type_list();
if (!in_array($device, $devices)) {
// The provided device isn't a valid device throw an error
print_error('invaliddevicetype');
}
}
unset($SESSION->theme);
if ($reset and confirm_sesskey()) {
theme_reset_all_caches();
} else if (($choose || $chooselegacy) && confirm_sesskey()) {
if ($choose) {
$chosentheme = $choose;
$heading = get_string('themesaved');
$config = 'theme';
} else {
$chosentheme = $chooselegacy;
$heading = get_string('legacythemesaved');
$config = 'themelegacy';
}
$theme = theme_config::load($chosentheme);
set_config($config, $theme->name);
} else if ($choose && $device && confirm_sesskey()) {
// Load the theme to make sure it is valid.
$theme = theme_config::load($choose);
// Get the config argument for the chosen device.
$themename = get_device_cfg_var_name($device);
set_config($themename, $theme->name);
// Create a new page for the display of the themes readme.
// This ensures that the readme page is shown using the new theme.
@@ -61,87 +64,132 @@ if ($reset and confirm_sesskey()) {
$output = $confirmpage->get_renderer('core');
echo $output->header();
echo $output->heading($heading);
echo $output->heading(get_string('themesaved'));
echo $output->box_start();
echo format_text(get_string('choosereadme', 'theme_'.$CFG->theme), FORMAT_MOODLE);
echo format_text(get_string('choosereadme', 'theme_'.$theme->name), FORMAT_MOODLE);
echo $output->box_end();
echo $output->continue_button($CFG->wwwroot . '/' . $CFG->admin . '/index.php');
echo $output->footer();
exit;
}
// Otherwise, show a list of themes.
// Otherwise, show either a list of devices, or is enabledevicedetection set to no or a
// device is specified show a list of themes.
echo $OUTPUT->header('themeselector');
echo $OUTPUT->heading(get_string('themes'));
echo $OUTPUT->single_button(new moodle_url('index.php', array('sesskey'=>sesskey(),'reset'=>1)), get_string('themeresetcaches', 'admin'));
echo $OUTPUT->single_button(new moodle_url('index.php', array('sesskey' => sesskey(), 'reset' => 1)), get_string('themeresetcaches', 'admin'));
$table = new html_table();
$table->id = 'adminthemeselector';
$table->head = array(get_string('theme'), get_string('info'));
$table->data = array();
if (!empty($CFG->enabledevicedetection) && empty($device)) {
// Display a list of devices that a user can select a theme for.
$themes = get_plugin_list('theme');
$strthemenotselected = get_string('themenoselected', 'admin');
$strthemeselect = get_string('themeselect', 'admin');
foreach ($themes as $themename => $themedir) {
// Display the device selection screen
$table->id = 'admindeviceselector';
$table->head = array(get_string('devicetype', 'admin'), get_string('theme'), get_string('info'));
// Load the theme config.
try {
$theme = theme_config::load($themename);
} catch (Exception $e) {
// Bad theme, just skip it for now.
continue;
$devices = get_device_type_list();
foreach ($devices as $device) {
$themename = get_selected_theme_for_device_type($device);
if (!$themename && $device == 'default') {
$themename = theme_config::DEFAULT_THEME;
}
$screenshotcell = $strthemenotselected;
if ($themename) {
// Check the theme exists
$themename = clean_param($themename, PARAM_THEME);
if (empty($themename)) {
// Likely the theme has been deleted
unset_config(get_device_cfg_var_name($device));
} else {
$strthemename = get_string('pluginname', 'theme_'.$themename);
// link to the screenshot, now mandatory - the image path is hardcoded because we need image from other themes, not the current one
$screenshoturl = new moodle_url('/theme/image.php', array('theme' => $themename, 'image' => 'screenshot', 'component' => 'theme'));
// Contents of the screenshot/preview cell.
$screenshotcell = html_writer::empty_tag('img', array('src' => $screenshoturl, 'alt' => $strthemename));
}
}
$deviceurl = new moodle_url('/theme/index.php', array('device' => $device, 'sesskey' => sesskey()));
$select = new single_button($deviceurl, $strthemeselect, 'get');
$table->data[] = array(
$device,
$screenshotcell,
$OUTPUT->render($select)
);
}
if ($themename !== $theme->name) {
//obsoleted or broken theme, just skip for now
continue;
}
if (!$CFG->themedesignermode && $theme->hidefromselector) {
// The theme doesn't want to be shown in the theme selector and as theme
// designer mode is switched off we will respect that decision.
continue;
}
$strthemename = get_string('pluginname', 'theme_'.$themename);
} else {
// Either a device has been selected of $CFG->enabledevicedetection is off so display a list
// of themes to select.
// Build the table row, and also a list of items to go in the second cell.
$row = array();
$infoitems = array();
$rowclasses = array();
// Set up bools whether this theme is chosen either main or legacy
$ischosentheme = ($themename == $CFG->theme);
$ischosenlegacytheme = (!empty($CFG->themelegacy) && $themename == $CFG->themelegacy);
if ($ischosentheme) {
// Is the chosen main theme
$rowclasses[] = 'selectedtheme';
}
if ($ischosenlegacytheme) {
// Is the chosen legacy theme
$rowclasses[] = 'selectedlegacytheme';
if (empty($device)) {
// if $CFG->enabledevicedetection is off this will return 'default'
$device = get_device_type();
}
// link to the screenshot, now mandatory - the image path is hardcoded because we need image from other themes, not the current one
$screenshotpath = new moodle_url('/theme/image.php', array('theme'=>$themename, 'image'=>'screenshot','component'=>'theme'));
// Contents of the first screenshot/preview cell.
$row[] = html_writer::empty_tag('img', array('src'=>$screenshotpath, 'alt'=>$strthemename));
$table->id = 'adminthemeselector';
$table->head = array(get_string('theme'), get_string('info'));
// Contents of the second cell.
$infocell = $OUTPUT->heading($strthemename, 3);
$themes = get_plugin_list('theme');
// Button to choose this as the main theme
$maintheme = new single_button(new moodle_url('/theme/index.php', array('choose' => $themename, 'sesskey' => sesskey())), get_string('useformaintheme'), 'get');
$maintheme->disabled = $ischosentheme;
$infocell .= $OUTPUT->render($maintheme);
foreach ($themes as $themename => $themedir) {
// Button to choose this as the legacy theme
$legacytheme = new single_button(new moodle_url('/theme/index.php', array('chooselegacy' => $themename, 'sesskey' => sesskey())), get_string('useforlegacytheme'), 'get');
$legacytheme->disabled = $ischosenlegacytheme;
$infocell .= $OUTPUT->render($legacytheme);
// Load the theme config.
try {
$theme = theme_config::load($themename);
} catch (Exception $e) {
// Bad theme, just skip it for now.
continue;
}
if ($themename !== $theme->name) {
//obsoleted or broken theme, just skip for now
continue;
}
if (!$CFG->themedesignermode && $theme->hidefromselector) {
// The theme doesn't want to be shown in the theme selector and as theme
// designer mode is switched off we will respect that decision.
continue;
}
$strthemename = get_string('pluginname', 'theme_'.$themename);
$row[] = $infocell;
// Build the table row, and also a list of items to go in the second cell.
$row = array();
$infoitems = array();
$rowclasses = array();
$table->data[$themename] = $row;
$table->rowclasses[$themename] = join(' ', $rowclasses);
// Set up bools whether this theme is chosen either main or legacy
$ischosentheme = ($themename == get_selected_theme_for_device_type($device));
if ($ischosentheme) {
// Is the chosen main theme
$rowclasses[] = 'selectedtheme';
}
// link to the screenshot, now mandatory - the image path is hardcoded because we need image from other themes, not the current one
$screenshotpath = new moodle_url('/theme/image.php', array('theme'=>$themename, 'image'=>'screenshot', 'component'=>'theme'));
// Contents of the first screenshot/preview cell.
$row[] = html_writer::empty_tag('img', array('src'=>$screenshotpath, 'alt'=>$strthemename));
// Contents of the second cell.
$infocell = $OUTPUT->heading($strthemename, 3);
// Button to choose this as the main theme
$maintheme = new single_button(new moodle_url('/theme/index.php', array('device' => $device, 'choose' => $themename, 'sesskey' => sesskey())), get_string('usetheme'), 'get');
$maintheme->disabled = $ischosentheme;
$infocell .= $OUTPUT->render($maintheme);
$row[] = $infocell;
$table->data[$themename] = $row;
$table->rowclasses[$themename] = join(' ', $rowclasses);
}
}
echo html_writer::table($table);
+33
View File
@@ -0,0 +1,33 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle 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 3 of the License, or
// (at your option) any later version.
//
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This code processes switch device requests-> ... -> Theme selector UI.
*
* This script doesn't require login as not logged in users should still
* be able to switch the device theme they are using.
*/
require('../config.php');
$url = required_param('url', PARAM_LOCALURL);
$newdevice = required_param('device', PARAM_TEXT);
require_sesskey();
set_user_device_type($newdevice);
redirect($url);
+1 -1
View File
@@ -30,7 +30,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2011060500.02; // YYYYMMDD = weekly release date of this DEV branch
$version = 2011060500.03; // YYYYMMDD = weekly release date of this DEV branch
// RR = release increments - 00 in DEV branches
// .XX = incremental changes