[MKDoc-commit] CSV patch from Sam
chris at mkdoc.demon.co.uk
chris at mkdoc.demon.co.uk
Mon May 9 10:12:52 BST 2005
Log Message:
-----------
CSV patch from Sam
Tags:
----
mkdoc-1-6
Modified Files:
--------------
mkd/templates/admin/user_list:
en.html
Added Files:
-----------
mkd/flo/plugin/Admin:
UserCSV.pm
-------------- next part --------------
--- /dev/null
+++ flo/plugin/Admin/UserCSV.pm
@@ -0,0 +1,278 @@
+package flo::plugin::Admin::UserCSV;
+use strict;
+use warnings;
+
+=head1 NAME
+
+flo::plugin::Admin::UserCSV - CSV download for user data
+
+=head1 SYNOPSIS
+
+Link to this plugin like so:
+
+ <a href=".admin.usercsv">Download the user CSV!</a>
+
+When clicked the client's browser will download a file called
+mkdoc_users.csv containing all user data.
+
+=head1 DESCRIPTION
+
+This plugin provides a CSV download of all user data.
+
+=head1 SUBCLASSING
+
+Two methods are provided to aid in subclassing this plugin:
+
+=head2 add_headers
+
+ @new_headers = $self->add_headers(@headers);
+
+This callback passes in the default list of headers. The return value
+is used as the new header list.
+
+=head2 add_data
+
+ @new_data = $self->add_data($user, @data);
+
+This callback passes in the row data for a single user. The return
+value is as the new data list. Obviously the order must match
+whatever changes are made in add_headers().
+
+=head1 AUTHOR
+
+Sam Tregar <sam at tregar.com>
+
+=head1 COPYRIGHT
+
+Copyright MKDoc Holdings Ltd, 2005
+
+=head1 LICENSE
+
+MKDoc is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+MKDoc is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with MKDoc; if not, write to the Free Software Foundation, Inc.,
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+=cut
+
+use flo::Standard;
+use base qw /flo::Plugin/;
+use Text::CSV_XS;
+use flo::Record::Preference::Audience qw(LIKE DONT_MIND HATE);
+
+# only admin can access this plugin
+sub activate {
+ my $self = shift;
+ $self->SUPER::activate(@_) || return;
+ $self->user()->id() == 1 || return;
+ return 1;
+}
+
+sub template_path { 'admin/unused' }
+
+# hooks for sub-classes
+sub add_headers {@_[1..$#_]}
+sub add_data {@_[1..$#_]}
+
+# return the CSV to the user
+sub http_get {
+ my $self = shift;
+
+ # setup header to get the browser to download as mkdoc_users.csv
+ my $header = new flo::HTTP::Header;
+ $header->set("Content-Type: application/x-download");
+ $header->set("Content-Disposition: attachment; filename=mkdoc_users.csv");
+ print $header->header;
+
+ # all done for head requests
+ return 'TERMINATE'
+ if $ENV{REQUEST_METHOD} and $ENV{REQUEST_METHOD} =~ /^HEAD$/i;
+
+ # build CSV output
+ $self->build_csv();
+
+ return 'TERMINATE';
+}
+
+# build the CSV using Text::CSV_XS
+sub build_csv {
+ my $self = shift;
+ my $csv = Text::CSV_XS->new({always_quote => 1,
+ binary => 1,
+ eol => "\n"});
+ my ($group_ids, $audience_ids, $language_ids) = $self->print_header($csv);
+
+ foreach my $user ($self->users()) {
+ my @data = $self->data_fields($user, $group_ids,
+ $audience_ids, $language_ids);
+ $self->print_row($csv, @data);
+ }
+}
+
+# prints out the header and returns IDs needed for row generation
+sub print_header {
+ my ($self, $csv) = @_;
+ my $dbh = lib::sql::DBH->get();
+
+ # get info for variable columns
+ my $results = $dbh->selectall_arrayref('SELECT ID, Name FROM Grp
+ ORDER BY Name');
+ my @group_names = map { $_->[1] } @$results;
+ my @group_ids = map { $_->[0] } @$results;
+
+ $results = $dbh->selectall_arrayref('SELECT ID, Label FROM Audience
+ ORDER BY Label');
+ my @audience_names = map { $_->[1] } @$results;
+ my @audience_ids = map { $_->[0] } @$results;
+
+ $results = $dbh->selectall_arrayref('SELECT DISTINCT(Language_ID)
+ FROM Preference_Language
+ ORDER BY Language_ID');
+ my @language_names = map { $_->[0] } @$results;
+ my @language_ids = @language_names;
+
+ my @headers = ( "Login",
+ "Email",
+ "First Name",
+ "Family Name",
+ "Disabled Status",
+ "Daily Newsletter",
+ "Weekly Newsletter",
+ "Monthly Newsletter",
+ "Editor Status",
+ "Documents Created",
+ (map { "$_ (Group)" } @group_names),
+ (map { "$_ (Audience)" } @audience_names),
+ (map { "$_ (Language)" } @language_names) );
+ @headers = $self->add_headers(@headers);
+
+ # print out CSV header
+ $self->print_row($csv, @headers);
+
+ return (\@group_ids, \@audience_ids, \@language_ids);
+}
+
+# encode booleans as "" for false or "0E0" and "TRUE" for all else
+sub _bool ($) {
+ my $val = shift;
+ $val ? ($val eq '0E0' ? "" : "TRUE") : "";
+}
+
+# output a single row of data
+sub data_fields {
+ my ($self, $user, $group_ids, $audience_ids, $language_ids) = @_;
+ my $pref = $user->preferences;
+
+ # login, email, first name, family name
+ my @data = map { $user->$_ } qw(login email first_name family_name);
+
+ # disabled status
+ push @data, _bool not $user->enabled;
+
+ # daily newsletter, weekly newsletter, monthly newsletter
+ push @data,
+ _bool $pref->general_preference('newsletter-daily'),
+ _bool $pref->general_preference('newsletter-weekly'),
+ _bool $pref->general_preference('newsletter-monthly');
+
+ # editor status
+ push @data, _bool($user->group eq 'editor');
+
+ # documents created
+ push @data, $self->documents_created($user);
+
+ # group membership
+ push @data, map { _bool($self->group_member($user, $_)) } @$group_ids;
+
+ # audicence membership
+ push @data, map { $self->audience_setting($user, $_) } @$audience_ids;
+
+ # language membership
+ push @data, map { $self->language_setting($user, $_) } @$language_ids;
+
+ return $self->add_data($user, @data);
+}
+
+# print a CSV row with error checking
+sub print_row {
+ my ($self, $csv, @data) = @_;
+ if ($csv->combine(@data)) {
+ print $csv->string;
+ } else {
+ my $err = $csv->error_input;
+ die "Text::CSV_XS::combine() failed on (" .
+ join(', ', map { defined($_) ? qq{'$_'} : "undef" } @data) . "): " .
+ $err;
+ }
+}
+
+# returns all uses as flo::Record::Editor objects (this could use an
+# iterator if there are too many users to load all at once)
+sub users {
+ my $self = shift;
+ my $editor_t = flo::Standard::table ('Editor');
+ my @res = $editor_t->select (
+ cols => '*',
+ sort => [ 'First_Name', 'Family_Name' ],
+ desc => 0,
+ )->fetch_all();
+
+ return wantarray ? @res : \@res;
+}
+
+sub documents_created {
+ my ($self, $user) = @_;
+ my $dbh = lib::sql::DBH->get();
+ my ($count) = $dbh->selectrow_array('SELECT COUNT(*) FROM Document
+ WHERE Editor_Created_ID = ?',
+ undef, $user->id);
+ return $count || 0;
+}
+
+sub group_member {
+ my ($self, $user, $grp_id) = @_;
+ my $dbh = lib::sql::DBH->get();
+
+ my ($exists) =
+ $dbh->selectrow_array('SELECT 1 FROM Editor_Grp
+ WHERE Grp_ID = ? AND Editor_ID = ?',
+ undef, $grp_id, $user->id);
+
+ return $exists;
+}
+
+
+sub audience_setting {
+ my ($self, $user, $aud_id) = @_;
+ my $dbh = lib::sql::DBH->get();
+
+ my ($value) =
+ $dbh->selectrow_array('SELECT Value FROM Preference_Audience
+ WHERE Audience_ID = ? AND Editor_ID = ?',
+ undef, $aud_id, $user->id);
+ $value ||= DONT_MIND;
+ return $value == LIKE ? "TRUE" : "";
+}
+
+sub language_setting {
+ my ($self, $user, $lang_id) = @_;
+ my $dbh = lib::sql::DBH->get();
+
+ my ($value) =
+ $dbh->selectrow_array('SELECT Value FROM Preference_Language
+ WHERE Language_ID = ? AND Editor_ID = ?',
+ undef, $lang_id, $user->id);
+ $value ||= DONT_MIND;
+ return $value == LIKE ? "TRUE" : "";
+}
+
+1;
Index: en.html
===================================================================
RCS file: /var/spool/cvs/mkd/templates/admin/user_list/Attic/en.html,v
retrieving revision 1.1.2.10
retrieving revision 1.1.2.11
diff -Ltemplates/admin/user_list/en.html -Ltemplates/admin/user_list/en.html -u -r1.1.2.10 -r1.1.2.11
--- templates/admin/user_list/en.html
+++ templates/admin/user_list/en.html
@@ -76,6 +76,16 @@
or edit or delete the existing users using the links in the following table.
</p>
+ <p
+ lang="en"
+ xml:lang="en"
+ dir="ltr"
+ >
+ <a
+ href=".admin.usercsv"
+ >Download user data CSV</a> for offline analysis.
+ </p>
+
<table
cellpadding="4"
cellspacing="0"
More information about the MKDoc-commit
mailing list