""" This file implements the Microsite support for the Open edX platform. A microsite enables the following features: 1) Mapping of sub-domain name to a 'brand', e.g. foo-university.edx.org 2) Present a landing page with a listing of courses that are specific to the 'brand' 3) Ability to swap out some branding elements in the website """ import threading import os.path from django.conf import settings CURRENT_REQUEST_CONFIGURATION = threading.local() CURRENT_REQUEST_CONFIGURATION.data = {} def has_configuration_set(): """ Returns whether there is any Microsite configuration settings """ return getattr(settings, "MICROSITE_CONFIGURATION", False) def get_configuration(): """ Returns the current request's microsite configuration """ if not hasattr(CURRENT_REQUEST_CONFIGURATION, 'data'): return {} return CURRENT_REQUEST_CONFIGURATION.data def is_request_in_microsite(): """ This will return if current request is a request within a microsite """ return bool(get_configuration()) def get_value(val_name, default=None): """ Returns a value associated with the request's microsite, if present """ configuration = get_configuration() return configuration.get(val_name, default) def has_override_value(val_name): """ Returns True/False whether a Microsite has a definition for the specified named value """ configuration = get_configuration() return val_name in configuration def get_template_path(relative_path): """ Returns a path (string) to a Mako template, which can either be in a microsite directory (as an override) or will just return what is passed in which is expected to be a string """ if not is_request_in_microsite(): return relative_path microsite_template_path = str(get_value('template_dir')) if microsite_template_path: search_path = os.path.join(microsite_template_path, relative_path) if os.path.isfile(search_path): path = '/{0}/templates/{1}'.format( get_value('microsite_name'), relative_path ) return path return relative_path def get_value_for_org(org, val_name, default=None): """ This returns a configuration value for a microsite which has an org_filter that matches what is passed in """ if not has_configuration_set(): return default for value in settings.MICROSITE_CONFIGURATION.values(): org_filter = value.get('course_org_filter', None) if org_filter == org: return value.get(val_name, default) return default def get_all_orgs(): """ This returns a set of orgs that are considered within a microsite. This can be used, for example, to do filtering """ org_filter_set = set() if not has_configuration_set(): return org_filter_set for value in settings.MICROSITE_CONFIGURATION.values(): org_filter = value.get('course_org_filter') if org_filter: org_filter_set.add(org_filter) return org_filter_set def clear(): """ Clears out any microsite configuration from the current request/thread """ CURRENT_REQUEST_CONFIGURATION.data = {} def _set_current_microsite(microsite_config_key, subdomain, domain): """ Helper internal method to actually put a microsite on the threadlocal """ config = settings.MICROSITE_CONFIGURATION[microsite_config_key].copy() config['subdomain'] = subdomain config['site_domain'] = domain CURRENT_REQUEST_CONFIGURATION.data = config def set_by_domain(domain): """ For a given request domain, find a match in our microsite configuration and then assign it to the thread local so that it is available throughout the entire Django request processing """ if not has_configuration_set() or not domain: return for key, value in settings.MICROSITE_CONFIGURATION.items(): subdomain = value.get('domain_prefix') if subdomain and domain.startswith(subdomain): _set_current_microsite(key, subdomain, domain) return # if no match on subdomain then see if there is a 'default' microsite defined # if so, then use that if 'default' in settings.MICROSITE_CONFIGURATION: _set_current_microsite('default', subdomain, domain)