Implemented Keyword Substitution feature

@jrbl @jinpa 

![screen shot 2014-07-18 at 4 02 35 pm](https://cloud.githubusercontent.com/assets/3598201/3632888/a5fc93d8-0ecf-11e4-8154-69c818781e70.png)
![screen shot 2014-07-18 at 4 02 11 pm](https://cloud.githubusercontent.com/assets/3598201/3632889/a5fca044-0ecf-11e4-9238-d42c842bf8c3.png)

With this commit, instructors can include keywords in their bulk emails and
announcments that will be automatically substituted to the corresponding value
in the database. This commit introduces: %%USER_ID%% => anonymous_user_id and
%%USER_NAMR%% => user profile name.

This substitution in done by common/djangoapps/util/keyword_substitution.py. It
has a map between keywords and functions that will be called on the original
string (html document), and replace each keyword with the return value of the
function. In order to add more keyword substitutions, we can just add
"%%keywords%%" and their function mappings to the map in the future.

In the future, we can use this module to introduce keyword substitution feature
in other places.

** Since this feature deals with anonymous user ids, it's dependent on: 
https://github.com/edx/edx-platform/pull/4485
@nedbat - that seems reasonable.   I have a vague memory that there was
some objection from a few people when we tried to add this information to
the HTML editor display so that people would know about it (see
https://github.com/edx/edx-platform/pull/1049) - how about instead of
reprising that discussion, we tell @mhoeber <https://github.com/mhoeber> about
it so that it can be explained as verbosely as needed for clarity in the
docs.  I like the idea of having the information visible in the Studio
interface, but I don't think that's universally agreed-on, so having it in
the Studio user docs would at least be a way of exposing it to people who
are trying to learn about available features.  Sound reasonable?


On Sat, Jul 19, 2014 at 5:35 AM, Ned Batchelder <notifications@github.com>
wrote:

> In lms/djangoapps/courseware/courses.py:
>
> > @@ -250,6 +251,7 @@ def get_course_info_section(request, course, section_key):
> >      if info_module is not None:
> >          try:
> >              html = info_module.render(STUDENT_VIEW).content
> > +            html = substitute_keywords_with_data(html, request.user.id, course.id)
>
> Have you described anywhere that the keyword substitution is also
> available on the course info page?
>
> —
> Reply to this email directly or view it on GitHub
> <https://github.com/edx/edx-platform/pull/4487/files#r15143512>.
>