diff options
-rw-r--r-- | Config.pm | 19 | ||||
-rw-r--r-- | Extension.pm | 94 | ||||
-rw-r--r-- | lib/Util.pm | 20 | ||||
-rw-r--r-- | template/en/default/global/banner.html.tmpl | 18 | ||||
-rw-r--r-- | template/en/default/global/header.html.tmpl | 313 | ||||
-rw-r--r-- | template/en/default/hook/README | 5 | ||||
-rw-r--r-- | template/en/default/hook/index-additional_links.html.tmpl | 13 | ||||
-rw-r--r-- | template/en/default/mageia/README | 16 | ||||
-rw-r--r-- | web/README | 7 | ||||
-rw-r--r-- | web/favicon.png | bin | 0 -> 1184 bytes |
10 files changed, 505 insertions, 0 deletions
diff --git a/Config.pm b/Config.pm new file mode 100644 index 0000000..4dbbda1 --- /dev/null +++ b/Config.pm @@ -0,0 +1,19 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::Mageia; +use strict; + +use constant NAME => 'Mageia'; + +use constant REQUIRED_MODULES => [ +]; + +use constant OPTIONAL_MODULES => [ +]; + +__PACKAGE__->NAME; diff --git a/Extension.pm b/Extension.pm new file mode 100644 index 0000000..4141e7c --- /dev/null +++ b/Extension.pm @@ -0,0 +1,94 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::Mageia; +use strict; +use base qw(Bugzilla::Extension); + +use Bugzilla::Bug; +use Bugzilla::Field; +use Bugzilla::User; +use Bugzilla::Extension::Mageia::Util; + +use Email::Address; + +our $VERSION = '0.10'; + +# sysadmin-bugs@ml.mageia.org user ID = 175. +use constant SYSADMIN_USER_ID => 175; + +sub bug_end_of_create_validators { + my ($self, $args) = @_; + + # If a user enters 'validated_update' as keyword, + # automatically CC sysadmin-bugs@ml.mageia.org. + my $keywords = $args->{params}->{keywords}; + + if (grep { $_->name eq 'validated_update' } @$keywords) { + my $cc_list = $args->{params}->{cc}; + if (!grep { $_ == SYSADMIN_USER_ID } @$cc_list) { + push(@$cc_list, SYSADMIN_USER_ID); + } + } +} + +sub bug_end_of_update { + my ($self, $args) = @_; + my $bug = $args->{bug}; + my $dbh = Bugzilla->dbh; + + # If a user enters 'validated_update' as keyword, + # automatically CC sysadmin-bugs@ml.mageia.org. + my $new_keywords_str = $args->{changes}->{keywords}->[1]; + + if ($new_keywords_str) { + my @new_keywords = split(/[,\s]+/, $new_keywords_str); + if (grep { $_ eq 'validated_update' } @new_keywords) { + if (!grep { $_->id == SYSADMIN_USER_ID } @{$bug->cc_users}) { + # Safer to clear the cache and let Bugzilla regenerate them if needed. + delete $bug->{cc_users}; + delete $bug->{cc}; + $dbh->do('INSERT INTO cc (bug_id, who) VALUES (?, ?)', + undef, ($bug->id, SYSADMIN_USER_ID)); + + # We also have to update the bug history to reflect this change. + my $changed_cc = $args->{changes}->{cc}; + my $sysadmin_login = user_id_to_login(SYSADMIN_USER_ID); + + if ($changed_cc->[1]) { + $changed_cc->[1] .= ", $sysadmin_login"; + } + else { + $changed_cc->[1] = $sysadmin_login; + } + + my $field_id = get_field_id('cc'); + $dbh->do('DELETE FROM bugs_activity + WHERE bug_id = ? AND bug_when = ? AND fieldid = ?', + undef, ($bug->id, $args->{timestamp}, $field_id)); + + LogActivityEntry($bug->id, 'cc', $changed_cc->[0] || '', $changed_cc->[1], + Bugzilla->user->id, $args->{timestamp}); + } + } + } +} + +sub mailer_before_send { + my ($self, $args) = @_; + my $email = $args->{email}; + + # Include the changer's name in the "From:" field. + if (my $changer = $email->header('X-Bugzilla-Who')) { + $changer = Bugzilla::User->new({ name => $changer }); + my $changer_name = $changer ? $changer->name : undef; + my $address = Email::Address->new($changer_name, $email->header('From')); + $email->header_set('From', $address->format); + } +} + +__PACKAGE__->NAME; diff --git a/lib/Util.pm b/lib/Util.pm new file mode 100644 index 0000000..7aa8b86 --- /dev/null +++ b/lib/Util.pm @@ -0,0 +1,20 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This Source Code Form is "Incompatible With Secondary Licenses", as +# defined by the Mozilla Public License, v. 2.0. + +package Bugzilla::Extension::Mageia::Util; +use strict; +use base qw(Exporter); +our @EXPORT = qw( + +); + +# This file can be loaded by your extension via +# "use Bugzilla::Extension::Mageia::Util". You can put functions +# used by your extension in here. (Make sure you also list them in +# @EXPORT.) + +1;
\ No newline at end of file diff --git a/template/en/default/global/banner.html.tmpl b/template/en/default/global/banner.html.tmpl new file mode 100644 index 0000000..d06f794 --- /dev/null +++ b/template/en/default/global/banner.html.tmpl @@ -0,0 +1,18 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +<script src="//nav.mageia.org/js/"></script> +<style> +body { margin: 0; padding-top: 0; background-color: #fff; } +div#wrap { background-color: #fff; } +#header, +#bugzilla-body { + margin: 0 1em 1em 1em; +} +</style> +<br> diff --git a/template/en/default/global/header.html.tmpl b/template/en/default/global/header.html.tmpl new file mode 100644 index 0000000..d01da1a --- /dev/null +++ b/template/en/default/global/header.html.tmpl @@ -0,0 +1,313 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[%# INTERFACE: + # (All the below interface elements are optional.) + # title: string. Page title. + # header: string. Main page header. + # subheader: string. Page subheader. + # header_addl_info: string. Additional header information. + # bodyclasses: array of extra CSS classes for the <body> + # onload: string. JavaScript code to run when the page finishes loading. + # javascript: string. Javascript to go in the header. + # javascript_urls: list. List of URLs to Javascript. + # style: string. CSS style. + # style_urls: list. List of URLs to CSS style sheets. + # message: string. A message to display to the user. May contain HTML. + # atomlink: Atom link URL, May contain HTML + #%] + +[% IF message %] + [% PROCESS global/messages.html.tmpl %] +[% END %] + +[% DEFAULT + subheader = "" + header_addl_info = "" + onload = "" + style_urls = [] + yui = [] +%] + +[% SET yui_css = { + autocomplete => 1, + calendar => 1, + datatable => 1, + button => 1, +} %] + +[%# Note: This is simple dependency resolution--you can't have dependencies + # that depend on each other. You have to specify all of a module's deps, + # if that module is going to be specified in "yui". + #%] +[% SET yui_deps = { + autocomplete => ['json', 'connection', 'datasource'], + datatable => ['json', 'connection', 'datasource', 'element'], +} %] + +[%# When using certain YUI modules, we need to process certain + # extra JS templates. + #%] +[% SET yui_templates = { + datatable => ['global/value-descs.js.tmpl'], +} %] + +[%# These are JS URLs that are *always* on the page and come before + # every other JS URL. + #%] +[% SET starting_js_urls = [ + "js/yui/yahoo-dom-event/yahoo-dom-event.js", + "js/yui/cookie/cookie-min.js", +] %] + + +[%# We should be able to set the default value of the header variable + # to the value of the title variable using the DEFAULT directive, + # but that doesn't work if a caller sets header to the empty string + # to avoid header inheriting the value of title, since DEFAULT + # mistakenly treats empty strings as undefined and gives header the + # value of title anyway. To get around that problem we explicitly + # set header's default value here only if it is undefined. %] +[% IF !header.defined %][% header = title %][% END %] + +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" + "http://www.w3.org/TR/html4/loose.dtd"> +<html lang="en"> + <head> + [% Hook.process("start") %] + <title>[% title %]</title> + + [% IF Param('utf8') %] + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + [% END %] + +[%# Migration note: contents of the old Param 'headerhtml' would go here %] + + [% PROCESS "global/site-navigation.html.tmpl" %] + + [% PROCESS 'global/setting-descs.none.tmpl' %] + + [% SET yui = yui_resolve_deps(yui, yui_deps) %] + [% SET css_sets = css_files(style_urls, yui, yui_css) %] + + [%# CSS cascade, parts 1 & 2: YUI & Standard Bugzilla stylesheet set (persistent). + # Always present. %] + <link href="[% 'skins/standard/global.css' FILTER mtime FILTER html %]" + rel="alternate stylesheet" + title="[% setting_descs.standard FILTER html %]"> + [% FOREACH style_url = css_sets.standard %] + [% PROCESS format_css_link css_set_name = 'standard' %] + [% END %] + + [%# CSS cascade, part 3: Third-party stylesheet set, per user prefs. %] + [% FOREACH style_url = css_sets.skin %] + [% PROCESS format_css_link css_set_name = user.settings.skin.value %] + [% END %] + + [%# CSS cascade, part 4: page-specific styles. %] + [% IF style %] + <style type="text/css"> + [% style %] + </style> + [% END %] + + [%# CSS cascade, part 5: Custom Bugzilla stylesheet set (persistent). + # Always present. Site administrators may override all other style + # definitions, including skins, using custom stylesheets. + #%] + [% FOREACH style_url = css_sets.custom %] + [% PROCESS format_css_link css_set_name = 'standard' %] + [% END %] + + [%# YUI Scripts %] + [% FOREACH yui_name = yui %] + [% starting_js_urls.push("js/yui/$yui_name/${yui_name}-min.js") %] + [% END %] + [% starting_js_urls.push('js/global.js') %] + + [% FOREACH javascript_url = starting_js_urls %] + [% PROCESS format_js_link %] + [% END %] + + <script type="text/javascript"> + <!-- + YAHOO.namespace('bugzilla'); + YAHOO.util.Event.addListener = function (el, sType, fn, obj, overrideContext) { + if ( ("onpagehide" in window || YAHOO.env.ua.gecko) && sType === "unload") { sType = "pagehide"; }; + var capture = ((sType == "focusin" || sType == "focusout") && !YAHOO.env.ua.ie) ? true : false; + return this._addListener(el, this._getType(sType), fn, obj, overrideContext, capture); + }; + if ( "onpagehide" in window || YAHOO.env.ua.gecko) { + YAHOO.util.Event._simpleRemove(window, "unload", + YAHOO.util.Event._unload); + } + [%# The language selector needs javascript to set its cookie, + # so it is hidden in HTML/CSS by the "bz_default_hidden" class. + # If the browser can run javascript, it will then "unhide" + # the language selector using the following code. + #%] + function unhide_language_selector() { + YAHOO.util.Dom.removeClass( + 'lang_links_container', 'bz_default_hidden' + ); + } + YAHOO.util.Event.onDOMReady(unhide_language_selector); + + [%# Make some Bugzilla information available to all scripts. + # We don't import every parameter and constant because we + # don't want to add a lot of uncached JS to every page. + #%] + var BUGZILLA = { + param: { + cookiepath: '[% Param('cookiepath') FILTER js %]', + maxusermatches: [% Param('maxusermatches') FILTER js %] + }, + constant: { + COMMENT_COLS: [% constants.COMMENT_COLS FILTER js %] + }, + string: { + [%# Please keep these in alphabetical order. %] + + attach_desc_required: + 'You must enter a Description for this attachment.', + component_required: + 'You must select a Component for this [% terms.bug %].', + description_required: + 'You must enter a Description for this [% terms.bug %].', + short_desc_required: + 'You must enter a Summary for this [% terms.bug %].', + version_required: + 'You must select a Version for this [% terms.bug %].' + } + }; + + [% FOREACH yui_name = yui %] + [% FOREACH yui_template = yui_templates.$yui_name %] + [% INCLUDE $yui_template %] + [% END %] + [% END %] + [% IF javascript %] + [% javascript %] + [% END %] + // --> + </script> + + [% FOREACH javascript_url = javascript_urls %] + [% PROCESS format_js_link %] + [% END %] + + [%# this puts the live bookmark up on firefox for the Atom feed %] + [% IF atomlink %] + <link rel="alternate" + type="application/atom+xml" title="Atom feed" + href="[% atomlink FILTER html %]"> + [% END %] + + [%# Required for the 'Autodiscovery' feature in Firefox 2 and IE 7. %] + <link rel="search" type="application/opensearchdescription+xml" + title="[% terms.Bugzilla %]" href="./search_plugin.cgi"> + <link rel="shortcut icon" href="extensions/Mageia/web/favicon.png" > + [% Hook.process("additional_header") %] + </head> + +[%# Migration note: contents of the old Param 'bodyhtml' go in the body tag, + # but set the onload attribute in the DEFAULT directive above. + #%] + + <body onload="[% onload %]" + class="[% urlbase.replace('^https?://','').replace('/$','').replace('[-~@:/.]+','-') FILTER css_class_quote %] + [% FOREACH class = bodyclasses %] + [% ' ' %][% class FILTER css_class_quote %] + [% END %] yui-skin-sam"> + +[%# Migration note: the following file corresponds to the old Param + # 'bannerhtml' + #%] + +<div id="header"> + +[% INCLUDE global/banner.html.tmpl %] + +<table border="0" cellspacing="0" cellpadding="0" id="titles"> +<tr> + <td id="title"> + <p>[% terms.Bugzilla %] + [% " – $header" IF header %]</p> + </td> + + [% IF subheader %] + <td id="subtitle"> + <p class="subheader">[% subheader %]</p> + </td> + [% END %] + + [% IF header_addl_info %] + <td id="information"> + <p class="header_addl_info">[% header_addl_info %]</p> + </td> + [% END %] +</tr> +</table> + +<table id="lang_links_container" cellpadding="0" cellspacing="0" + class="bz_default_hidden"><tr><td> +[% IF Bugzilla.languages.size > 1 %] + <ul class="links"> + [% FOREACH lang = Bugzilla.languages.sort %] + <li>[% IF NOT loop.first %]<span class="separator"> | </span>[% END %] + [% IF lang == current_language %] + <span class="lang_current">[% lang FILTER html FILTER upper %]</span> + [% ELSE %] + <a href="#" onclick="set_language('[% lang FILTER none %]');"> + [%- lang FILTER html FILTER upper %]</a> + [% END %] + </li> + [% END %] + </ul> +[% END %] +</td></tr></table> + +[% PROCESS "global/common-links.html.tmpl" qs_suffix = "_top" %] +</div> [%# header %] + +<div id="bugzilla-body"> + +[% IF Param('announcehtml') %] +[% Param('announcehtml') FILTER none %] +[% END %] + +[% IF message %] + <div id="message">[% message %]</div> +[% END %] + +[% BLOCK format_css_link %] + [% IF style_url.match('/IE-fixes\.css') %] + <!--[if lte IE 7]> + [%# Internet Explorer treats [if IE] HTML comments as uncommented. + # We use it to import CSS fixes so that Bugzilla looks decent on IE 7 + # and below. + #%] + [% END %] + + [% IF css_set_name == 'standard' %] + [% SET css_title_link = '' %] + [% ELSE %] + [% css_title_link = BLOCK ~%] + title="[% setting_descs.${user.settings.skin.value} || user.settings.skin.value FILTER html %]" + [% END %] + [% END %] + + <link href="[% style_url FILTER html %]" rel="stylesheet" + type="text/css" [% css_title_link FILTER none %]> + + [% '<![endif]-->' IF style_url.match('/IE-fixes\.css') %] +[% END %] + +[% BLOCK format_js_link %] + <script type="text/javascript" src="[% javascript_url FILTER mtime FILTER html %]"></script> +[% END %] diff --git a/template/en/default/hook/README b/template/en/default/hook/README new file mode 100644 index 0000000..e6c4add --- /dev/null +++ b/template/en/default/hook/README @@ -0,0 +1,5 @@ +Template hooks go in this directory. Template hooks are called in normal +Bugzilla templates like [% Hook.process('some-hook') %]. +More information about them can be found in the documentation of +Bugzilla::Extension. (Do "perldoc Bugzilla::Extension" from the main +Bugzilla directory to see that documentation.)
\ No newline at end of file diff --git a/template/en/default/hook/index-additional_links.html.tmpl b/template/en/default/hook/index-additional_links.html.tmpl new file mode 100644 index 0000000..695cd1f --- /dev/null +++ b/template/en/default/hook/index-additional_links.html.tmpl @@ -0,0 +1,13 @@ +[%# This Source Code Form is subject to the terms of the Mozilla Public + # License, v. 2.0. If a copy of the MPL was not distributed with this + # file, You can obtain one at http://mozilla.org/MPL/2.0/. + # + # This Source Code Form is "Incompatible With Secondary Licenses", as + # defined by the Mozilla Public License, v. 2.0. + #%] + +[% UNLESS user.id %] + <p style="border: solid 1px; background-color: #ffd386; color: #9b1a1a; padding: 1em;"> + Don't have an account on [% terms.Bugzilla %]? Click <a href="http://identity.mageia.org/register">here</a> to create one. + </p> +[% END %]
\ No newline at end of file diff --git a/template/en/default/mageia/README b/template/en/default/mageia/README new file mode 100644 index 0000000..099d1a4 --- /dev/null +++ b/template/en/default/mageia/README @@ -0,0 +1,16 @@ +Normal templates go in this directory. You can load them in your +code like this: + +use Bugzilla::Error; +my $template = Bugzilla->template; +$template->process('mageia/some-template.html.tmpl') + or ThrowTemplateError($template->error()); + +That would be how to load a file called some-template.html.tmpl that +was in this directory. + +Note that you have to be careful that the full path of your template +never conflicts with a template that exists in Bugzilla or in +another extension, or your template might override that template. That's why +we created this directory called 'mageia' for you, so you +can put your templates in here to help avoid conflicts.
\ No newline at end of file diff --git a/web/README b/web/README new file mode 100644 index 0000000..2345641 --- /dev/null +++ b/web/README @@ -0,0 +1,7 @@ +Web-accessible files, like JavaScript, CSS, and images go in this +directory. You can reference them directly in your HTML. For example, +if you have a file called "style.css" and your extension is called +"Foo", you would put it in "extensions/Foo/web/style.css", and then +you could link to it in HTML like: + +<link href="extensions/Foo/web/style.css" rel="stylesheet" type="text/css">
\ No newline at end of file diff --git a/web/favicon.png b/web/favicon.png Binary files differnew file mode 100644 index 0000000..5868d96 --- /dev/null +++ b/web/favicon.png |