Example #1
0
def perform_regenerate_issue(issue,
                             journal_name,
                             ln=CFG_SITE_LANG,
                             confirmed_p=False,
                             publish_draft_articles_p=False):
    """
    Clears the cache for the given issue.

    Parameters:

                 journal_name -  the journal for which the cache should
                                 be deleted
                        issue -  the issue for which the cache should be
                                 deleted
                          ln  -  language
                 confirmed_p  -  if True, regenerate. Else ask confirmation
    publish_draft_articles_p  -  should the remaining draft articles in
                                 the issue be made public?
    """

    if not confirmed_p:
        # Ask user confirmation about the regeneration
        current_issue = get_current_issue(ln, journal_name)
        issue_released_p = not issue_is_later_than(issue, current_issue)
        return wjt.tmpl_admin_regenerate_confirm(ln,
                                                 journal_name,
                                                 issue,
                                                 issue_released_p)
    else:
        # Regenerate the issue (clear the cache)
        success = clear_cache_for_issue(journal_name,
                                        issue)
        if publish_draft_articles_p:
            current_issue = get_current_issue(ln, journal_name)
            if not issue_is_later_than(issue, current_issue):
                # This issue is already released: we can safely publish
                # the articles. Otherwise we'll refuse to publish the drafts
                move_drafts_articles_to_ready(journal_name, issue)

        if success:
            return wjt.tmpl_admin_regenerate_success(ln,
                                                     journal_name,
                                                     issue)
        else:
            return wjt.tmpl_admin_regenerate_error(ln,
                                                   journal_name,
                                                   issue)
Example #2
0
def perform_regenerate_issue(issue,
                             journal_name,
                             ln=CFG_SITE_LANG,
                             confirmed_p=False,
                             publish_draft_articles_p=False):
    """
    Clears the cache for the given issue.

    Parameters:

                 journal_name -  the journal for which the cache should
                                 be deleted
                        issue -  the issue for which the cache should be
                                 deleted
                          ln  -  language
                 confirmed_p  -  if True, regenerate. Else ask confirmation
    publish_draft_articles_p  -  should the remaining draft articles in
                                 the issue be made public?
    """

    if not confirmed_p:
        # Ask user confirmation about the regeneration
        current_issue = get_current_issue(ln, journal_name)
        issue_released_p = not issue_is_later_than(issue, current_issue)
        return wjt.tmpl_admin_regenerate_confirm(ln,
                                                 journal_name,
                                                 issue,
                                                 issue_released_p)
    else:
        # Regenerate the issue (clear the cache)
        success = clear_cache_for_issue(journal_name,
                                        issue)
        if publish_draft_articles_p:
            current_issue = get_current_issue(ln, journal_name)
            if not issue_is_later_than(issue, current_issue):
                # This issue is already released: we can safely publish
                # the articles. Otherwise we'll refuse to publish the drafts
                move_drafts_articles_to_ready(journal_name, issue)

        if success:
            return wjt.tmpl_admin_regenerate_success(ln,
                                                     journal_name,
                                                     issue)
        else:
            return wjt.tmpl_admin_regenerate_error(ln,
                                                   journal_name,
                                                   issue)
Example #3
0
def perform_request_index(req, journal_name, issue_number, ln,
                          category, editor=False, verbose=0):
    """
    Central logic function for index pages.
    Brings together format templates and MARC rules from the config, with
    the requested index page, given by the url parameters.
    From config:
        - page template for index pages -> formatting
        - MARC rule list -> Category Navigation
        - MARC tag used for issue numbers -> search (later in the format
          elements)
    Uses BibFormatObject and format_with_format_template to produce the
    required HTML.
    """
    current_issue = get_current_issue(ln, journal_name)
    if not get_release_datetime(issue_number, journal_name):
        # Unreleased issue. Display latest released issue?
        unreleased_issues_mode = get_unreleased_issue_hiding_mode(journal_name)
        if not editor and \
               (unreleased_issues_mode == 'all' or \
                (unreleased_issues_mode == 'future' and \
                 issue_is_later_than(issue_number, current_issue))):
            redirect_to_url(req, "%s/journal/%s/%s/%s?ln=%s" % \
                            (CFG_SITE_URL,
                             journal_name,
                             current_issue.split('/')[1],
                             current_issue.split('/')[0],
                             ln))
    try:
        index_page_template = get_journal_template('index',
                                                   journal_name,
                                                   ln)
    except InvenioWebJournalTemplateNotFoundError as e:
        register_exception(req=req)
        return e.user_box(req)

    temp_marc = '''<record>
                        <controlfield tag="001">0</controlfield>
                    </record>'''
    # create a record and get HTML back from bibformat
    user_info = collect_user_info(req)
    bfo = BibFormatObject(0, ln=ln, xml_record=temp_marc,
                          user_info=user_info)
    bfo.req = req
    verbosity = 0
    if editor:
        # Increase verbosity only for editors/admins
        verbosity = verbose

    html = format_with_format_template(index_page_template,
                                       bfo,
                                       verbose=verbosity)
    return html
def format_element(bfo, new_articles_first='yes',
           subject_to_css_class_kb="WebJournalSubject2CSSClass",
           display_all_category_articles='no', display_category_title='no'):
    """
    List all articles one after the other, on the same page.

    Similar to bfe_webjournal_articles_overview, but displays full articles.

    Note that you cannot use both bfe_webjournal_articles_overview and
    bfe_webjournal_articles: you have to choose one of them, as they
    use the same cache location (It would also not make sense to use
    both...).

    @param new_articles_first: if 'yes', display new articles before other articles
    @param subject_to_css_class_kb: knowledge base that maps 595__a to a CSS class
    @param display_all_category_articles: if yes, display all articles, whatever category is selected
    @param display_category_title: if yes, display category title (useful if display_all_category_articles is enabled)

    @see: bfe_webjournal_articles_overview.py
    """
    args = parse_url_string(bfo.user_info['uri'])
    journal_name = args["journal_name"]
    this_issue_number = args["issue"]
    category_name = args["category"]
    verbose = args["verbose"]
    ln = bfo.lang
    _ = gettext_set_language(ln)

    # Try to get the page from cache. Only if issue is older or equal
    # to latest release.
    latest_released_issue = get_current_issue(ln, journal_name)
    if verbose == 0 and not issue_is_later_than(this_issue_number,
                                                latest_released_issue):
        cached_html = get_index_page_from_cache(journal_name, category_name,
                                                this_issue_number, ln)
        if cached_html:
            return cached_html

    # Shall we display current category, or all?
    categories = [category_name]
    if display_all_category_articles.lower() == 'yes':
        categories = get_journal_categories(journal_name,
                                            this_issue_number)

    out = ''
    for category_name in categories:
        if display_category_title.lower() == 'yes':
            out += '<h2>' + _(category_name) + '</h2>'

        out += '<table border="0" cellpadding="0" cellspacing="0">'
        # Get the id list
        ordered_articles = get_journal_articles(journal_name,
                                                this_issue_number,
                                                category_name,
                                                newest_first=new_articles_first.lower() == 'yes')
        new_articles_only = False
        if ordered_articles.keys() and max(ordered_articles.keys()) < 0:
            # If there are only new articles, don't bother marking them as
            # new
            new_articles_only = True

        order_numbers = ordered_articles.keys()
        order_numbers.sort()

        for order_number in order_numbers:
            for article_id in ordered_articles[order_number]:
                # A record is considered as new if its position is
                # negative and there are some non-new articles
                article_is_new = (order_number < 0 and not new_articles_only)

                temp_rec = BibFormatObject(article_id)
                title = ''
                if ln == "fr":
                    title = temp_rec.field('246_1a')
                    if title == '':
                        title = temp_rec.field('245__a')
                else:
                    title = temp_rec.field('245__a')
                    if title == '':
                        title = temp_rec.field('246_1a')

                # Get CSS class (if relevant)
                notes = temp_rec.fields('595__a')
                css_classes = [temp_rec.kb(subject_to_css_class_kb, note, None) \
                               for note in notes]
                css_classes = [css_class for css_class in css_classes \
                               if css_class is not None]

                if article_is_new:
                    css_classes.append('new')

                # Finally create the output. Two different outputs
                # depending on if we have text to display or not
                text = []
                if ln == "fr":
                    text = temp_rec.fields('590__b')
                    if not text or \
                           (len(text) == 1 and \
                            (text[0].strip() in ['', '<br />', '<!--HTML--><br />'])):
                        text = temp_rec.fields('520__b')
                else:
                    text = temp_rec.fields('520__b')
                    if not text or \
                           (len(text) == 1 and \
                            (text[0].strip() in ['', '<br />', '<!--HTML--><br />'])):
                        text = temp_rec.fields('590__b')
                text = '<br/>'.join(text)


                out += '''
                            <tr><td class="article">
                               <h%(header_tag_size)s class="%(css_classes)s articleTitle" style="clear:both;">
                                   %(title)s
                               </h%(header_tag_size)s>
                               <div class="articleBody">
                                   <div class="articleText">
                                      %(text)s
                                   </div>
                               </div>
                           </td></tr>
                        ''' % {'title': title,
                               'text': text,
                               'header_tag_size': (display_category_title.lower() == 'yes') and '3' or '2',
                               'css_classes': ' '.join(css_classes)}
        out += '</table>'

    if verbose == 0 and not CFG_ACCESS_CONTROL_LEVEL_SITE == 2 :
        cache_index_page(out, journal_name, category_name,
                         this_issue_number, ln)

    return out
Example #5
0
def perform_request_article(req, journal_name, issue_number, ln,
                            category, recid, editor=False, verbose=0):
    """
    Central logic function for article pages.
    Loads the format template for article display and displays the requested
    article using BibFormat.
    'Editor' mode generates edit links on the article view page and disables
    caching.
    """
    current_issue = get_current_issue(ln, journal_name)
    if not get_release_datetime(issue_number, journal_name):
        # Unreleased issue. Display latest released issue?
        unreleased_issues_mode = get_unreleased_issue_hiding_mode(journal_name)
        if not editor and \
               (unreleased_issues_mode == 'all' or \
                (unreleased_issues_mode == 'future' and \
                 issue_is_later_than(issue_number, current_issue))):
            redirect_to_url(req, "%s/journal/%s/%s/%s?ln=%s" % \
                            (CFG_SITE_URL,
                             journal_name,
                             current_issue.split('/')[1],
                             current_issue.split('/')[0],
                             ln))

    try:
        index_page_template = get_journal_template('detailed',
                                                   journal_name,
                                                   ln)
    except InvenioWebJournalTemplateNotFoundError as e:
        register_exception(req=req)
        return e.user_box(req)

    user_info = collect_user_info(req)
    bfo = BibFormatObject(recid, ln=ln, user_info=user_info)
    bfo.req = req

    # if it is cached, return it
    cached_html = get_article_page_from_cache(journal_name, category,
                                              recid, issue_number, ln,
                                              bfo)

    if cached_html and not editor:
        return cached_html

    # Check that this recid is indeed an article
    is_article = False
    articles = get_journal_articles(journal_name, issue_number, category)
    for order, recids in iteritems(articles):
        if recid in recids:
            is_article = True
            break

    if not is_article:
        redirect_to_url(req, "%s/journal/%s/%s/%s?ln=%s" % \
                        (CFG_SITE_URL,
                         journal_name,
                         issue_number.split('/')[1],
                         issue_number.split('/')[0],
                         ln))


    # create a record and get HTML back from bibformat
    verbosity = 0
    if editor:
        # Increase verbosity only for editors/admins
        verbosity = verbose
    html_out = format_with_format_template(index_page_template,
                                           bfo,
                                           verbose=verbosity)
    # cache if not in editor mode, and if database is not down
    if not editor and not CFG_ACCESS_CONTROL_LEVEL_SITE == 2:
        cache_article_page(html_out, journal_name, category,
                           recid, issue_number, ln)

    return html_out
def format_element(bfo, number_of_featured_articles="1",
           number_of_articles_with_image="3", new_articles_first='yes',
           image_px_width="300", small_image_px_width="200",
           subject_to_css_class_kb="WebJournalSubject2CSSClass",
           link_image_to_article='yes', image_alignment='left'):
    """
    Creates an overview of all the articles of a certain category in one
    specific issue.

    Note the following:
    <ul>
    <li>The element consider only the latest issue: when viewing
    archives of your journal, readers will see the newest articles of
    the latest issue, not the ones of the issue they are looking
    at</li>

    <li>This is not an index of the articles of the latest issue: it
    display only <b>new</b> articles, that is articles that have never
    appeared in a previous issue</li>

    <li>This element produces a table-based layout, in order to have a
    more or less readable HTML alert when sent some Email clients
    (Outlook 2007)</li>

    <li>When producing the HTML output of images, this element tries to
    insert the width and height attributes to the img tag: this is
    necessary in order to produce nice HTML alerts. This dimension
    therefore overrides any dimension defined in the CSS. The Python
    Image Library (PIL) should be installed for this element to
    recognize the size of images.</li>
    </ul>

    @param number_of_featured_articles: the max number of records with emphasized title
    @param number_of_articles_with_image: the max number of records for which their image is displayed
    @param new_articles_first: if 'yes', display new articles before other articles
    @param image_px_width: (integer) width of first image featured on this page
    @param small_image_px_width: (integer) width of small images featured on this page
    @param subject_to_css_class_kb: knowledge base that maps 595__a to a CSS class
    @param link_image_to_article: if 'yes', link image (if any) to article
    @param image_alignment: 'left', 'center' or 'right'. To help rendering in Outlook.
    """
    args = parse_url_string(bfo.user_info['uri'])
    journal_name = args["journal_name"]
    this_issue_number = args["issue"]
    category_name = args["category"]
    verbose = args["verbose"]
    ln = bfo.lang
    _ = gettext_set_language(ln)

    if image_px_width.isdigit():
        image_px_width = int(image_px_width)
    else:
        image_px_width = None
    if small_image_px_width.isdigit():
        small_image_px_width = int(small_image_px_width)
    else:
        small_image_px_width = None

    # We want to put emphasis on the n first articles (which are not
    # new)
    if number_of_featured_articles.isdigit():
        number_of_featured_articles = int(number_of_featured_articles)
    else:
        number_of_featured_articles = 0

    # Only n first articles will display images
    if number_of_articles_with_image.isdigit():
        number_of_articles_with_image = int(number_of_articles_with_image)
    else:
        number_of_articles_with_image = 0

    # Help image alignement without CSS, to have better rendering in Outlook
    img_align = ''
    if image_alignment:
        img_align = 'align="%s"' % image_alignment

    # Try to get the page from cache. Only if issue is older or equal
    # to latest release.
    latest_released_issue = get_current_issue(ln, journal_name)
    if verbose == 0 and not issue_is_later_than(this_issue_number,
                                                latest_released_issue):
        cached_html = get_index_page_from_cache(journal_name, category_name,
                                                this_issue_number, ln)
        if cached_html:
            return cached_html

    out = '<table border="0" cellpadding="0" cellspacing="0">'
    # Get the id list
    ordered_articles = get_journal_articles(journal_name,
                                            this_issue_number,
                                            category_name,
                                            newest_first=new_articles_first.lower() == 'yes')
    new_articles_only = False
    if ordered_articles.keys() and max(ordered_articles.keys()) < 0:
        # If there are only new articles, don't bother marking them as
        # new
        new_articles_only = True

    order_numbers = ordered_articles.keys()
    order_numbers.sort()
    img_css_class = "featuredImageScale"

    for order_number in order_numbers:
        for article_id in ordered_articles[order_number]:
            # A record is considered as new if its position is
            # negative and there are some non-new articles
            article_is_new = (order_number < 0 and not new_articles_only)

            temp_rec = BibFormatObject(article_id)
            title = ''
            if ln == "fr":
                title = temp_rec.field('246_1a')
                if title == '':
                    title = temp_rec.field('245__a')
            else:
                title = temp_rec.field('245__a')
                if title == '':
                    title = temp_rec.field('246_1a')

            # Get CSS class (if relevant)
            notes = temp_rec.fields('595__a')
            css_classes = [temp_rec.kb(subject_to_css_class_kb, note, None) \
                           for note in notes]
            css_classes = [css_class for css_class in css_classes \
                           if css_class is not None]

            if article_is_new:
                css_classes.append('new')

            # Maybe we want to force image to appear?
            display_image_on_index = False
            if 'display_image_on_index' in notes:
                display_image_on_index = True

            # Build generic link to this article
            article_link = make_journal_url(bfo.user_info['uri'], {'recid':str(article_id),
                                                                   'ln': bfo.lang})

            # Build the "more" link
            more_link = '''<a class="readMore" title="link to the article" href="%s"> &gt;&gt; </a>
                        ''' % (article_link)

            # If we should display an image along with the text,
            # prepare it here
            img = ''
            if (number_of_articles_with_image > 0 and \
                   not article_is_new) or display_image_on_index:
                img = _get_feature_image(temp_rec, ln)
                if img != "":
                    # Now we will try to identify image size in order
                    # to resize it in the HTML for a nicer rendering
                    # of the HTML alert in email clients (Outlook wants
                    # both height and width)
                    img_width = None
                    img_height = None
                    small_img_width = None
                    small_img_height = None
                    width_and_height = ''
                    if PIL_imported:
                        try:
                            local_img = os.path.join(CFG_TMPDIR,
                                                     'webjournal_' + \
                                                     ''.join([char for char in img \
                                                              if char.isalnum()]))
                            if len(local_img) > 255:
                                # Shorten to 255 chars
                                local_img = local_img[0:100] + '_' + local_img[156:]
                            if not os.path.exists(local_img):
                                # Too bad, must download entire image for PIL
                                content_type = get_content_type(img)
                                if 'image' in content_type:
                                    (local_img, headers) = urllib.urlretrieve(img, local_img)
                                    img_file = Image.open(local_img) # IOError if not readable image
                                else:
                                    raise IOError('Not an image')
                            else:
                                img_file = Image.open(local_img) # IOError if not readable image
                        except IOError as e:
                            pass
                        else:
                            orig_img_width = img_file.size[0]
                            orig_img_height = img_file.size[1]
                            # Then scale according to user-defined width
                            ## First image
                            ratio = float(orig_img_width) / image_px_width
                            img_width = image_px_width
                            img_height = int(orig_img_height / ratio)
                            ## Other smaller images
                            ratio = float(orig_img_width) / small_image_px_width
                            small_img_width = small_image_px_width
                            small_img_height = int(orig_img_height / ratio)

                    # Note that we cannot reuse the nice phl, ph and
                    # phr classes to put a frame around the image:
                    # this is not supported in Outlook 2007 when HTML
                    # alert is sent.
                    if not img_css_class == "featuredImageScale":
                        # Not first image: display smaller
                        img_width = small_img_width
                        img_height = small_img_height

                    if img_width and img_height:
                        width_and_height = 'width="%i" height="%i"' % \
                                           (img_width, img_height)
                    img = '<img alt="" class="%s" src="%s" %s %s/>' % \
                          (img_css_class, img, img_align, width_and_height)
                    number_of_articles_with_image -= 1

                    # Next images will be displayed smaller
                    img_css_class = "featuredImageScaleSmall"

            # Determine size of the title
            header_tag_size = '3'
            if number_of_featured_articles > 0 and \
                   not article_is_new:
                # n first articles are especially featured
                header_tag_size = '2'
                number_of_featured_articles -= 1

            # Finally create the output. Two different outputs
            # depending on if we have text to display or not
            text = ''
            if not article_is_new:
                text = _get_feature_text(temp_rec, ln)
            # Link image to article if wanted
            if link_image_to_article.lower() == 'yes':
                img = create_html_link(urlbase=article_link,
                                       link_label=img,
                                       urlargd={})
            if text != '':
                out += '''
                        <tr><td class="article">
                           <h%(header_tag_size)s class="%(css_classes)s articleTitle" style="clear:both;">
                               <a title="link to the article" href="%(article_link)s">%(title)s</a>
                           </h%(header_tag_size)s>
                           <div class="articleBody">
                               %(img)s
                               %(text)s
                               %(more_link)s
                           </div>
                       </td></tr>
                    ''' % {'article_link': article_link,
                           'title': title,
                           'img': img,
                           'text': text,
                           'more_link': more_link,
                           'css_classes': ' '.join(css_classes),
                           'header_tag_size': header_tag_size}
            else:
                out += '''
                       <tr><td class="article">
                           <h%(header_tag_size)s class="%(css_classes)s articleTitle" style="clear:both;">
                               <a title="link to the article" href="%(article_link)s">%(title)s</a>&nbsp;&nbsp;
                               %(more_link)s
                           </h%(header_tag_size)s>
                           %(img)s
                       </td></tr>
                       ''' % {'article_link': article_link,
                              'title': title,
                              'more_link': more_link,
                              'img': img,
                              'css_classes': ' '.join(css_classes),
                              'header_tag_size': header_tag_size}
    out += '</table>'
    if verbose == 0 and not CFG_ACCESS_CONTROL_LEVEL_SITE == 2 :
        cache_index_page(out, journal_name, category_name,
                         this_issue_number, ln)

    return out
def format_element(bfo,
                   new_articles_first='yes',
                   subject_to_css_class_kb="WebJournalSubject2CSSClass",
                   display_all_category_articles='no',
                   display_category_title='no'):
    """
    List all articles one after the other, on the same page.

    Similar to bfe_webjournal_articles_overview, but displays full articles.

    Note that you cannot use both bfe_webjournal_articles_overview and
    bfe_webjournal_articles: you have to choose one of them, as they
    use the same cache location (It would also not make sense to use
    both...).

    @param new_articles_first: if 'yes', display new articles before other articles
    @param subject_to_css_class_kb: knowledge base that maps 595__a to a CSS class
    @param display_all_category_articles: if yes, display all articles, whatever category is selected
    @param display_category_title: if yes, display category title (useful if display_all_category_articles is enabled)

    @see: bfe_webjournal_articles_overview.py
    """
    args = parse_url_string(bfo.user_info['uri'])
    journal_name = args["journal_name"]
    this_issue_number = args["issue"]
    category_name = args["category"]
    verbose = args["verbose"]
    ln = bfo.lang
    _ = gettext_set_language(ln)

    # Try to get the page from cache. Only if issue is older or equal
    # to latest release.
    latest_released_issue = get_current_issue(ln, journal_name)
    if verbose == 0 and not issue_is_later_than(this_issue_number,
                                                latest_released_issue):
        cached_html = get_index_page_from_cache(journal_name, category_name,
                                                this_issue_number, ln)
        if cached_html:
            return cached_html

    # Shall we display current category, or all?
    categories = [category_name]
    if display_all_category_articles.lower() == 'yes':
        categories = get_journal_categories(journal_name, this_issue_number)

    out = ''
    for category_name in categories:
        if display_category_title.lower() == 'yes':
            out += '<h2>' + _(category_name) + '</h2>'

        out += '<table border="0" cellpadding="0" cellspacing="0">'
        # Get the id list
        ordered_articles = get_journal_articles(
            journal_name,
            this_issue_number,
            category_name,
            newest_first=new_articles_first.lower() == 'yes')
        new_articles_only = False
        if ordered_articles.keys() and max(ordered_articles.keys()) < 0:
            # If there are only new articles, don't bother marking them as
            # new
            new_articles_only = True

        order_numbers = ordered_articles.keys()
        order_numbers.sort()

        for order_number in order_numbers:
            for article_id in ordered_articles[order_number]:
                # A record is considered as new if its position is
                # negative and there are some non-new articles
                article_is_new = (order_number < 0 and not new_articles_only)

                temp_rec = BibFormatObject(article_id)
                title = ''
                if ln == "fr":
                    title = temp_rec.field('246_1a')
                    if title == '':
                        title = temp_rec.field('245__a')
                else:
                    title = temp_rec.field('245__a')
                    if title == '':
                        title = temp_rec.field('246_1a')

                # Get CSS class (if relevant)
                notes = temp_rec.fields('595__a')
                css_classes = [temp_rec.kb(subject_to_css_class_kb, note, None) \
                               for note in notes]
                css_classes = [css_class for css_class in css_classes \
                               if css_class is not None]

                if article_is_new:
                    css_classes.append('new')

                # Finally create the output. Two different outputs
                # depending on if we have text to display or not
                text = []
                if ln == "fr":
                    text = temp_rec.fields('590__b')
                    if not text or \
                           (len(text) == 1 and \
                            (text[0].strip() in ['', '<br />', '<!--HTML--><br />'])):
                        text = temp_rec.fields('520__b')
                else:
                    text = temp_rec.fields('520__b')
                    if not text or \
                           (len(text) == 1 and \
                            (text[0].strip() in ['', '<br />', '<!--HTML--><br />'])):
                        text = temp_rec.fields('590__b')
                text = '<br/>'.join(text)

                out += '''
                            <tr><td class="article">
                               <h%(header_tag_size)s class="%(css_classes)s articleTitle" style="clear:both;">
                                   %(title)s
                               </h%(header_tag_size)s>
                               <div class="articleBody">
                                   <div class="articleText">
                                      %(text)s
                                   </div>
                               </div>
                           </td></tr>
                        ''' % {
                    'title':
                    title,
                    'text':
                    text,
                    'header_tag_size':
                    (display_category_title.lower() == 'yes') and '3' or '2',
                    'css_classes':
                    ' '.join(css_classes)
                }
        out += '</table>'

    if verbose == 0 and not CFG_ACCESS_CONTROL_LEVEL_SITE == 2:
        cache_index_page(out, journal_name, category_name, this_issue_number,
                         ln)

    return out
def format_element(bfo,
                   number_of_featured_articles="1",
                   number_of_articles_with_image="3",
                   new_articles_first='yes',
                   image_px_width="300",
                   small_image_px_width="200",
                   subject_to_css_class_kb="WebJournalSubject2CSSClass",
                   link_image_to_article='yes',
                   image_alignment='left'):
    """
    Creates an overview of all the articles of a certain category in one
    specific issue.

    Note the following:
    <ul>
    <li>The element consider only the latest issue: when viewing
    archives of your journal, readers will see the newest articles of
    the latest issue, not the ones of the issue they are looking
    at</li>

    <li>This is not an index of the articles of the latest issue: it
    display only <b>new</b> articles, that is articles that have never
    appeared in a previous issue</li>

    <li>This element produces a table-based layout, in order to have a
    more or less readable HTML alert when sent some Email clients
    (Outlook 2007)</li>

    <li>When producing the HTML output of images, this element tries to
    insert the width and height attributes to the img tag: this is
    necessary in order to produce nice HTML alerts. This dimension
    therefore overrides any dimension defined in the CSS. The Python
    Image Library (PIL) should be installed for this element to
    recognize the size of images.</li>
    </ul>

    @param number_of_featured_articles: the max number of records with emphasized title
    @param number_of_articles_with_image: the max number of records for which their image is displayed
    @param new_articles_first: if 'yes', display new articles before other articles
    @param image_px_width: (integer) width of first image featured on this page
    @param small_image_px_width: (integer) width of small images featured on this page
    @param subject_to_css_class_kb: knowledge base that maps 595__a to a CSS class
    @param link_image_to_article: if 'yes', link image (if any) to article
    @param image_alignment: 'left', 'center' or 'right'. To help rendering in Outlook.
    """
    args = parse_url_string(bfo.user_info['uri'])
    journal_name = args["journal_name"]
    this_issue_number = args["issue"]
    category_name = args["category"]
    verbose = args["verbose"]
    ln = bfo.lang
    _ = gettext_set_language(ln)

    if image_px_width.isdigit():
        image_px_width = int(image_px_width)
    else:
        image_px_width = None
    if small_image_px_width.isdigit():
        small_image_px_width = int(small_image_px_width)
    else:
        small_image_px_width = None

    # We want to put emphasis on the n first articles (which are not
    # new)
    if number_of_featured_articles.isdigit():
        number_of_featured_articles = int(number_of_featured_articles)
    else:
        number_of_featured_articles = 0

    # Only n first articles will display images
    if number_of_articles_with_image.isdigit():
        number_of_articles_with_image = int(number_of_articles_with_image)
    else:
        number_of_articles_with_image = 0

    # Help image alignement without CSS, to have better rendering in Outlook
    img_align = ''
    if image_alignment:
        img_align = 'align="%s"' % image_alignment

    # Try to get the page from cache. Only if issue is older or equal
    # to latest release.
    latest_released_issue = get_current_issue(ln, journal_name)
    if verbose == 0 and not issue_is_later_than(this_issue_number,
                                                latest_released_issue):
        cached_html = get_index_page_from_cache(journal_name, category_name,
                                                this_issue_number, ln)
        if cached_html:
            return cached_html

    out = '<table border="0" cellpadding="0" cellspacing="0">'
    # Get the id list
    ordered_articles = get_journal_articles(
        journal_name,
        this_issue_number,
        category_name,
        newest_first=new_articles_first.lower() == 'yes')
    new_articles_only = False
    if ordered_articles.keys() and max(ordered_articles.keys()) < 0:
        # If there are only new articles, don't bother marking them as
        # new
        new_articles_only = True

    order_numbers = ordered_articles.keys()
    order_numbers.sort()
    img_css_class = "featuredImageScale"

    for order_number in order_numbers:
        for article_id in ordered_articles[order_number]:
            # A record is considered as new if its position is
            # negative and there are some non-new articles
            article_is_new = (order_number < 0 and not new_articles_only)

            temp_rec = BibFormatObject(article_id)
            title = ''
            if ln == "fr":
                title = temp_rec.field('246_1a')
                if title == '':
                    title = temp_rec.field('245__a')
            else:
                title = temp_rec.field('245__a')
                if title == '':
                    title = temp_rec.field('246_1a')

            # Get CSS class (if relevant)
            notes = temp_rec.fields('595__a')
            css_classes = [temp_rec.kb(subject_to_css_class_kb, note, None) \
                           for note in notes]
            css_classes = [css_class for css_class in css_classes \
                           if css_class is not None]

            if article_is_new:
                css_classes.append('new')

            # Maybe we want to force image to appear?
            display_image_on_index = False
            if 'display_image_on_index' in notes:
                display_image_on_index = True

            # Build generic link to this article
            article_link = make_journal_url(bfo.user_info['uri'], {
                'recid': str(article_id),
                'ln': bfo.lang
            })

            # Build the "more" link
            more_link = '''<a class="readMore" title="link to the article" href="%s"> &gt;&gt; </a>
                        ''' % (article_link)

            # If we should display an image along with the text,
            # prepare it here
            img = ''
            if (number_of_articles_with_image > 0 and \
                   not article_is_new) or display_image_on_index:
                img = _get_feature_image(temp_rec, ln)
                if img != "":
                    # Now we will try to identify image size in order
                    # to resize it in the HTML for a nicer rendering
                    # of the HTML alert in email clients (Outlook wants
                    # both height and width)
                    img_width = None
                    img_height = None
                    small_img_width = None
                    small_img_height = None
                    width_and_height = ''
                    if PIL_imported:
                        try:
                            local_img = os.path.join(CFG_TMPDIR,
                                                     'webjournal_' + \
                                                     ''.join([char for char in img \
                                                              if char.isalnum()]))
                            if len(local_img) > 255:
                                # Shorten to 255 chars
                                local_img = local_img[0:100] + '_' + local_img[
                                    156:]
                            if not os.path.exists(local_img):
                                # Too bad, must download entire image for PIL
                                content_type = get_content_type(img)
                                if 'image' in content_type:
                                    (local_img, headers) = urllib.urlretrieve(
                                        img, local_img)
                                    img_file = Image.open(
                                        local_img
                                    )  # IOError if not readable image
                                else:
                                    raise IOError('Not an image')
                            else:
                                img_file = Image.open(
                                    local_img)  # IOError if not readable image
                        except IOError as e:
                            pass
                        else:
                            orig_img_width = img_file.size[0]
                            orig_img_height = img_file.size[1]
                            # Then scale according to user-defined width
                            ## First image
                            ratio = float(orig_img_width) / image_px_width
                            img_width = image_px_width
                            img_height = int(orig_img_height / ratio)
                            ## Other smaller images
                            ratio = float(
                                orig_img_width) / small_image_px_width
                            small_img_width = small_image_px_width
                            small_img_height = int(orig_img_height / ratio)

                    # Note that we cannot reuse the nice phl, ph and
                    # phr classes to put a frame around the image:
                    # this is not supported in Outlook 2007 when HTML
                    # alert is sent.
                    if not img_css_class == "featuredImageScale":
                        # Not first image: display smaller
                        img_width = small_img_width
                        img_height = small_img_height

                    if img_width and img_height:
                        width_and_height = 'width="%i" height="%i"' % \
                                           (img_width, img_height)
                    img = '<img alt="" class="%s" src="%s" %s %s/>' % \
                          (img_css_class, img, img_align, width_and_height)
                    number_of_articles_with_image -= 1

                    # Next images will be displayed smaller
                    img_css_class = "featuredImageScaleSmall"

            # Determine size of the title
            header_tag_size = '3'
            if number_of_featured_articles > 0 and \
                   not article_is_new:
                # n first articles are especially featured
                header_tag_size = '2'
                number_of_featured_articles -= 1

            # Finally create the output. Two different outputs
            # depending on if we have text to display or not
            text = ''
            if not article_is_new:
                text = _get_feature_text(temp_rec, ln)
            # Link image to article if wanted
            if link_image_to_article.lower() == 'yes':
                img = create_html_link(urlbase=article_link,
                                       link_label=img,
                                       urlargd={})
            if text != '':
                out += '''
                        <tr><td class="article">
                           <h%(header_tag_size)s class="%(css_classes)s articleTitle" style="clear:both;">
                               <a title="link to the article" href="%(article_link)s">%(title)s</a>
                           </h%(header_tag_size)s>
                           <div class="articleBody">
                               %(img)s
                               %(text)s
                               %(more_link)s
                           </div>
                       </td></tr>
                    ''' % {
                    'article_link': article_link,
                    'title': title,
                    'img': img,
                    'text': text,
                    'more_link': more_link,
                    'css_classes': ' '.join(css_classes),
                    'header_tag_size': header_tag_size
                }
            else:
                out += '''
                       <tr><td class="article">
                           <h%(header_tag_size)s class="%(css_classes)s articleTitle" style="clear:both;">
                               <a title="link to the article" href="%(article_link)s">%(title)s</a>&nbsp;&nbsp;
                               %(more_link)s
                           </h%(header_tag_size)s>
                           %(img)s
                       </td></tr>
                       ''' % {
                    'article_link': article_link,
                    'title': title,
                    'more_link': more_link,
                    'img': img,
                    'css_classes': ' '.join(css_classes),
                    'header_tag_size': header_tag_size
                }
    out += '</table>'
    if verbose == 0 and not CFG_ACCESS_CONTROL_LEVEL_SITE == 2:
        cache_index_page(out, journal_name, category_name, this_issue_number,
                         ln)

    return out