summaryrefslogtreecommitdiffstats
path: root/extensions/Push/lib/Util.pm
blob: bda6331bfa3c54bef8da160b784d3dcaa5067f0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# 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::Push::Util;

use 5.10.1;
use strict;
use warnings;

use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::Util qw(datetime_from trim);
use Data::Dumper;
use Encode;
use JSON ();
use Scalar::Util qw(blessed);
use Time::HiRes;

use base qw(Exporter);
our @EXPORT = qw(
    datetime_to_timestamp
    debug_dump
    get_first_value
    hash_undef_to_empty
    is_public
    mapr
    clean_error
    change_set_id
    canon_email
    to_json from_json
);

# returns true if the specified object is public
sub is_public {
    my ($object) = @_;

    my $default_user = Bugzilla::User->new();

    if ($object->isa('Bugzilla::Bug')) {
        return unless $default_user->can_see_bug($object->bug_id);
        return 1;

    } elsif ($object->isa('Bugzilla::Comment')) {
        return if $object->is_private;
        return unless $default_user->can_see_bug($object->bug_id);
        return 1;

    } elsif ($object->isa('Bugzilla::Attachment')) {
        return if $object->isprivate;
        return unless $default_user->can_see_bug($object->bug_id);
        return 1;

    } else {
        warn "Unsupported class " . blessed($object) . " passed to is_public()\n";
    }

    return 1;
}

# return the first existing value from the hashref for the given list of keys
sub get_first_value {
    my ($rh, @keys) = @_;
    foreach my $field (@keys) {
        return $rh->{$field} if exists $rh->{$field};
    }
    return;
}

# wrapper for map that works on array references
sub mapr(&$) {
    my ($filter, $ra) = @_;
    my @result = map(&$filter, @$ra);
    return \@result;
}


# convert datetime string (from db) to a UTC json friendly datetime
sub datetime_to_timestamp {
    my ($datetime_string) = @_;
    return '' unless $datetime_string;
    return datetime_from($datetime_string, 'UTC')->datetime();
}

# replaces all undef values in a hashref with an empty string (deep)
sub hash_undef_to_empty {
    my ($rh) = @_;
    foreach my $key (keys %$rh) {
        my $value = $rh->{$key};
        if (!defined($value)) {
            $rh->{$key} = '';
        } elsif (ref($value) eq 'HASH') {
            hash_undef_to_empty($value);
        }
    }
}

# debugging methods
sub debug_dump {
    my ($object) = @_;
    local $Data::Dumper::Sortkeys = 1;
    my $output = Dumper($object);
    $output =~ s/</&lt;/g;
    print "<pre>$output</pre>";
}

# removes stacktrace and "at /some/path ..." from errors
sub clean_error {
    my ($error) = @_;
    my $path = bz_locations->{'extensionsdir'};
    $error = $1 if $error =~ /^(.+?) at \Q$path/s;
    $path = '/loader/0x';
    $error = $1 if $error =~ /^(.+?) at \Q$path/s;
    $error =~ s/(^\s+|\s+$)//g;
    return $error;
}

# generate a new change_set id
sub change_set_id {
    return "$$." . Time::HiRes::time();
}

# remove guff from email addresses
sub clean_email {
    my $email = shift;
    $email = trim($email);
    $email = $1 if $email =~ /^(\S+)/;
    $email =~ s/&#64;/@/;
    $email = lc $email;
    return $email;
}

# resolve to canonised email form
# eg. glob+bmo@mozilla.com --> glob@mozilla.com
sub canon_email {
    my $email = shift;
    $email = clean_email($email);
    $email =~ s/^([^\+]+)\+[^\@]+(\@.+)$/$1$2/;
    return $email;
}

# json helpers
sub to_json {
    my ($object, $pretty) = @_;
    if ($pretty) {
        return decode('utf8', JSON->new->utf8(1)->pretty(1)->encode($object));
    } else {
        return JSON->new->ascii(1)->shrink(1)->encode($object);
    }
}

sub from_json {
    my ($json) = @_;
    if (utf8::is_utf8($json)) {
        $json = encode('utf8', $json);
    }
    return JSON->new->utf8(1)->decode($json);
}

1;