package WebGUI::PassiveAnalytics::Flow; use strict; use Tie::IxHash; use WebGUI::AdminConsole; use WebGUI::HTMLForm; use WebGUI::International; use WebGUI::Pluggable; use WebGUI::PassiveAnalytics::Rule; use WebGUI::Utility; use WebGUI::HTMLForm; use WebGUI::Workflow; use WebGUI::Workflow::Instance; use WebGUI::User; use WebGUI::Text; use WebGUI::Fork; =head1 NAME Package WebGUI::PassiveAnalytics::Flow =head1 DESCRIPTION Web interface for making sets of rules for doing passive analytics, and running them. =cut #---------------------------------------------------------------------------- =head2 analysisActive ( session ) Returns true if an instance of the PassiveAnalytics workflow is active. =cut sub analysisActive { my $session = shift; my ($running, $startDate, $endDate, $userId) = $session->db->quickArray(q!select running, startDate, endDate, userId from passiveAnalyticsStatus!); if (wantarray) { return $running, $startDate, $endDate, WebGUI::User->new($session, $userId); } return $running; } #---------------------------------------------------------------------------- =head2 canView ( session [, user] ) Returns true if the user can administrate this operation. user defaults to the current user. =cut sub canView { my $session = shift; my $user = shift || $session->user; return $user->isInGroup( 3 ); } #---------------------------------------------------------------------------- =head2 exportSomething ( $process, $data ) Generates CSV data from the supplied statement handle and generates a temporary WebGUI::Storage object containing that data in the requested filename. This subroutine also does a setRedirect to the URL of the file in the storage object. =head3 $process A WebGUI::Fork object, to let the user know what's going on. =head3 $data Hash ref of data. =head3 tableName The name of the table where data will be pulled and translated into CSV. =head3 filename The name of the file to generate =cut sub exportSomething { my ($process, $data) = @_; my $session = $process->session; my $i18n = WebGUI::International->new($session, 'Asset_Thingy'); my $storage = WebGUI::Storage->createTemp($session); open my $CSV, '>', $storage->getPath($data->{filename}); my $sth = $session->db->read('select SQL_CALC_FOUND_ROWS * from '.$data->{tableName}); my %status = ( current => 0, message => '', total => $session->db->quickScalar('select found_rows()') + 0, ); my $update = sub { $process->update( sub { JSON::to_json(\%status) } ); }; $update->(); my @columns = $sth->getColumnNames; print $CSV WebGUI::Text::joinCSV( @columns ). "\n"; my $rowCounter = 0; $status{message} = $i18n->get('Writing data'); $update->(); while (my $row = $sth->hashRef()) { my @row = @{ $row }{@columns}; print $CSV WebGUI::Text::joinCSV(@row) . "\n"; ++$status{current }; $update->(); } close $CSV; $sth->finish; $process->setRedirect($storage->getUrl($data->{filename})); $status{message} = sprintf '%s', $session->url->page('op=passiveAnalytics;func=editRuleflow'), 'Return to Passive Analytics'; $update->(); } #------------------------------------------------------------------- =head2 www_deleteRule ( ) Deletes an activity from a workflow. =cut sub www_deleteRule { my $session = shift; return $session->privilege->insufficient() unless canView($session); my $rule = WebGUI::PassiveAnalytics::Rule->new($session, $session->form->get("ruleId")); if (defined $rule) { $rule->delete; } return www_editRuleflow($session); } #------------------------------------------------------------------ =head2 www_demoteRule ( session ) Moves a Rule down one position in the execution order. =head3 session A reference to the current session. =cut sub www_demoteRule { my $session = shift; return $session->privilege->insufficient() unless canView($session); my $rule = WebGUI::PassiveAnalytics::Rule->new($session, $session->form->get("ruleId")); if (defined $rule) { $rule->demote; } return www_editRuleflow($session); } #------------------------------------------------------------------- =head2 www_editRuleflow ( $session, $error ) Configure a set of analyses to run on the passive logs. The analysis is destructive. =head3 $error Allows another method to pass an error into this method, to display to the user. =cut sub www_editRuleflow { my $session = shift; my $error = shift; return $session->privilege->insufficient() unless canView($session); my ($running, $startDate, $endDate, $user) = analysisActive($session); if ($error) { $error = qq|
$error
\n|; } elsif (!$running) { $error = qq|
Passive Analytics analysis completed on $endDate
\n|; } my $i18n = WebGUI::International->new($session, "PassiveAnalytics"); my $addmenu = '
'; $addmenu .= sprintf '%s', $session->url->page('op=passiveAnalytics;func=editRule'), $i18n->get('Add a bucket'); $addmenu .= '
'; my $f = WebGUI::HTMLForm->new($session); $f->hidden( name=>'op', value=>'passiveAnalytics' ); $f->hidden( name=>'func', value=>'editRuleflowSave' ); $f->integer( name => 'pauseInterval', value => $session->form->get('pauseInterval') || $session->setting->get('passiveAnalyticsInterval') || 300, label => $i18n->get('pause interval'), hoverHelp => $i18n->get('pause interval help'), ); if ($running) { $f->raw(sprintf <username); Passive Analytics analysis is currently active. Analysis was begun at %s by %s EOD } else { $f->submit(value => $i18n->get('Begin analysis')); } my $steps = ''; my $getARule = WebGUI::PassiveAnalytics::Rule->getAllIterator($session); my $icon = $session->icon; while (my $rule = $getARule->()) { my $id = $rule->getId; my $bucket = $rule->get('bucketName'); $steps .= ''; } $steps .= '
' . $icon->delete( 'op=passiveAnalytics;func=deleteRule;ruleId='.$id, undef, $i18n->get('confirm delete rule')) . $icon->edit( 'op=passiveAnalytics;func=editRule;ruleId='.$id) . $icon->moveDown('op=passiveAnalytics;func=demoteRule;ruleId='.$id) . $icon->moveUp( 'op=passiveAnalytics;func=promoteRule;ruleId='.$id) . ''.$bucket.'
 Other
'; my $ac = WebGUI::AdminConsole->new($session,'passiveAnalytics'); $ac->addSubmenuItem($session->url->page('op=passiveAnalytics;func=settings'), $i18n->get('Passive Analytics Settings')); if (!$running) { $ac->addSubmenuItem($session->url->page('op=passiveAnalytics;func=exportBucketData'), $i18n->get('Export bucket data')); $ac->addSubmenuItem($session->url->page('op=passiveAnalytics;func=exportDeltaData'), $i18n->get('Export delta data')); $ac->addSubmenuItem($session->url->page('op=passiveAnalytics;func=exportLogs'), $i18n->get('Export raw logs')); } return $ac->render($error.$f->print.$addmenu.$steps, 'Passive Analytics'); } #------------------------------------------------------------------- =head2 www_editRuleflowSave ( ) Saves the results of www_editRuleflow() =cut sub www_editRuleflowSave { my $session = shift; return $session->privilege->insufficient() unless canView($session); my $i18n = WebGUI::International->new($session, 'PassiveAnalytics'); return www_editRuleflow($session, $i18n->get('already active')) if analysisActive($session); my $workflow = WebGUI::Workflow->new($session, 'PassiveAnalytics000001'); return www_editRuleflow($session, $i18n->get('workflow deleted')) unless defined $workflow; my $delta = $session->form->process('pauseInterval','integer'); my $activities = $workflow->getActivities(); ##Note, they're in order, and the order is known. $activities->[0]->set('deltaInterval', $delta); $activities->[1]->set('userId', $session->user->userId); my $instance = WebGUI::Workflow::Instance->create($session, { workflowId => $workflow->getId, priority => 1, }); if (!defined $instance) { return www_editRuleflow($session, $i18n->get('currently running')) if $session->stow->get('singletonWorkflowClash'); return www_editRuleflow($session, $i18n->get('error creating workflow')); } $instance->start('skipRealtime'); $session->db->write('update passiveAnalyticsStatus set startDate=NOW(), userId=?, endDate=?, running=1', [$session->user->userId, '']); return www_editRuleflow($session); } #------------------------------------------------------------------- =head2 www_editRule ( ) Displays a form to edit the properties rule. =cut sub www_editRule { my ($session, $error) = @_; return $session->privilege->insufficient() unless canView($session); if ($error) { $error = qq|
$error
\n|; } ##Make a PassiveAnalytics rule to use to populate the form. my $ruleId = $session->form->get('ruleId'); my $rule; if ($ruleId) { $rule = WebGUI::PassiveAnalytics::Rule->new($session, $ruleId); } else { ##We need a temporary rule so that we can call dynamicForm, below $ruleId = 'new'; $rule = WebGUI::PassiveAnalytics::Rule->create($session, {}); } ##Build the form my $form = WebGUI::HTMLForm->new($session); $form->hidden( name=>"op", value=>"passiveAnalytics"); $form->hidden( name=>"func", value=>"editRuleSave"); $form->hidden( name=>"ruleId", value=>$ruleId); $form->dynamicForm([WebGUI::PassiveAnalytics::Rule->crud_definition($session)], 'properties', $rule); $form->submit; my $i18n = WebGUI::International->new($session, 'PassiveAnalytics'); my $ac = WebGUI::AdminConsole->new($session,'passiveAnalytics'); $ac->addSubmenuItem($session->url->page("op=passiveAnalytics;func=editRuleflow"), $i18n->get("manage ruleset")); if ($ruleId eq 'new') { $rule->delete; } return $ac->render($error.$form->print,$i18n->get('Edit Rule')); } #------------------------------------------------------------------- =head2 www_editRuleSave ( ) Saves the results of www_editRule(). =cut sub www_editRuleSave { my $session = shift; my $form = $session->form; return $session->privilege->insufficient() unless canView($session); my $regexp = $form->get('regexp'); eval { 'fooBarBaz' =~ qr/$regexp/; }; if ($@) { my $error = $@; $error =~ s/at \S+?\.pm line \d+.*$//; my $i18n = WebGUI::International->new($session, 'PassiveAnalytics'); $error = join ' ', $i18n->get('Regular Expression Error:'), $error; return www_editRule($session, $error); } my $ruleId = $form->get('ruleId'); my $rule; if ($ruleId eq 'new') { $rule = WebGUI::PassiveAnalytics::Rule->create($session, {}); } else { $rule = WebGUI::PassiveAnalytics::Rule->new($session, $ruleId); } $rule->updateFromFormPost if $rule; return www_editRuleflow($session); } #------------------------------------------------------------------- =head2 www_exportBucketData ( ) Dump the contents of the bucket log. =cut sub www_exportBucketData { my ($session) = @_; my $process = WebGUI::Fork->start( $session, __PACKAGE__, 'exportSomething', { tableName => 'bucketLog', filename => 'bucketData.csv', }, ); my $i18n = WebGUI::International->new($session, 'PassiveAnalytics'); $session->http->setRedirect( $session->url->page( $process->contentPairs( 'ProgressBar', { icon => 'passiveAnalytics', title => $i18n->get('Export bucket data'), proceed => $session->url->page('op=passiveAnalytics;func=editRuleflow'), }, ), ), ); return "redirect"; } #------------------------------------------------------------------- =head2 www_exportDeltaData ( ) Dump the contents of the delta log. =cut sub www_exportDeltaData { my ($session) = @_; my $process = WebGUI::Fork->start( $session, __PACKAGE__, 'exportSomething', { tableName => 'deltaLog', filename => 'deltaData.csv', }, ); my $i18n = WebGUI::International->new($session, 'PassiveAnalytics'); $session->http->setRedirect( $session->url->page( $process->contentPairs( 'ProgressBar', { icon => 'passiveAnalytics', title => $i18n->get('Export delta data'), proceed => $session->url->page('op=passiveAnalytics;func=editRuleflow'), }, ), ), ); return "redirect"; } #------------------------------------------------------------------- =head2 www_exportLogs ( ) Dump the contents of the raw log. =cut sub www_exportLogs { my ($session) = @_; my $process = WebGUI::Fork->start( $session, __PACKAGE__, 'exportSomething', { tableName => 'passiveLog', filename => 'passiveData.csv', }, ); my $i18n = WebGUI::International->new($session, 'PassiveAnalytics'); $session->http->setRedirect( $session->url->page( $process->contentPairs( 'ProgressBar', { icon => 'passiveAnalytics', title => $i18n->get('Export raw logs'), proceed => $session->url->page('op=passiveAnalytics;func=editRuleflow'), }, ), ), ); return "redirect"; } #------------------------------------------------------------------ =head2 www_promoteRule ( session ) Moves a rule up one position in the execution order. =head3 session A reference to the current session. =cut sub www_promoteRule { my $session = shift; return $session->privilege->insufficient() unless canView($session); my $rule = WebGUI::PassiveAnalytics::Rule->new($session, $session->form->get("ruleId")); if (defined $rule) { $rule->promote; } return www_editRuleflow($session); } #------------------------------------------------------------------- =head2 www_settings ( session ) Configure Passive Analytics settings. =cut sub www_settings { my $session = shift; my $error = shift; return $session->privilege->insufficient() unless canView($session); if ($error) { $error = qq|
$error
\n|; } my $i18n = WebGUI::International->new($session, "PassiveAnalytics"); my $f = WebGUI::HTMLForm->new($session); $f->hidden( name=>'op', value=>'passiveAnalytics' ); $f->hidden( name=>'func', value=>'settingsSave' ); $f->integer( name => 'pauseInterval', value => $session->form->get('pauseInterval') || $session->setting->get('passiveAnalyticsInterval') || 300, label => $i18n->get('default pause interval'), hoverHelp => $i18n->get('default pause interval help'), ); $f->yesNo( name => 'deleteDelta', value => $session->form->get('deleteDelta') || $session->setting->get('passiveAnalyticsDeleteDelta') || 0, label => $i18n->get('Delete Delta Table?'), hoverHelp => $i18n->get('Delete Delta Table? help'), ); $f->yesNo( name => 'enabled', value => $session->form->get('enabled') || $session->setting->get('passiveAnalyticsEnabled') || 0, label => $i18n->get('Enabled?'), hoverHelp => $i18n->get('Enabled? help'), ); $f->submit(); my $ac = WebGUI::AdminConsole->new($session,'passiveAnalytics'); $ac->addSubmenuItem($session->url->page('op=passiveAnalytics;func=editRuleflow'), $i18n->get('Passive Analytics')); return $ac->render($error.$f->print, 'Passive Analytics Settings'); } #------------------------------------------------------------------- =head2 www_settingsSave ( session ) Save Passive Analytics settings. =cut sub www_settingsSave { my $session = shift; return $session->privilege->insufficient() unless canView($session); my $form = $session->form; $session->setting->set('passiveAnalyticsInterval', $form->process('pauseInterval', 'integer')); $session->setting->set('passiveAnalyticsDeleteDelta', $form->process('deleteDelta', 'yesNo' )); $session->setting->set('passiveAnalyticsEnabled', $form->process('enabled', 'yesNo' )); return www_settings($session); } 1;