Seditio Source
Root |
./othercms/ips_4.3.4/applications/nexus/modules/admin/support/reports.php
<?php
/**
 * @brief        Support Reports
 * @author        <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
 * @copyright    (c) Invision Power Services, Inc.
 * @license        https://www.invisioncommunity.com/legal/standards/
 * @package        Invision Community
 * @subpackage    Nexus
 * @since        23 Apr 2014
 */

namespace IPS\nexus\modules\admin\support;

/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
   
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
    exit;
}

/**
 * Support Reports
 */
class _reports extends \IPS\Dispatcher\Controller
{
   
/**
     * Execute
     *
     * @return    void
     */
   
public function execute()
    {
        \
IPS\Dispatcher::i()->checkAcpPermission( 'reports_manage' );
       
parent::execute();
    }

   
/**
     * Dashboard
     *
     * @return    void
     */
   
protected function manage()
    {
       
/* Tabs */
       
$tabs = array(
           
'overview'             => 'overview',
           
'replies'             => 'latest_replies',
           
'feedback_ratings'     => 'feedback_ratings',
           
'latest_feedback'    => 'latest_feedback',
        );
       
$activeTab = ( isset( \IPS\Request::i()->tab ) and array_key_exists( \IPS\Request::i()->tab, $tabs ) ) ? \IPS\Request::i()->tab : 'staff_productivity';
       
$activeTabContents = '';
       
       
/* Staff Productivity */
       
if ( $activeTab === 'overview' )
        {
           
/* Filters */
           
$filters = array(
               
'last_24_hours'    => \IPS\DateTime::create()->sub( new \DateInterval( 'P1D' ) )->getTimestamp(),
               
'last_7_days'    => \IPS\DateTime::create()->sub( new \DateInterval( 'P7D' ) )->getTimestamp(),
               
'last_30_days'    => \IPS\DateTime::create()->sub( new \DateInterval( 'P30D' ) )->getTimestamp(),
            );
           
           
/* Set default values */
           
$data = array();
            foreach ( \
IPS\nexus\Support\Request::staff() as $staffId => $name )
            {
               
$data[ $staffId ] = array( 'name' => $name, 'reply_count' => 0 );
                if ( \
IPS\Settings::i()->nexus_support_satisfaction )
                {
                   
$data[ $staffId ]['rating_count'] = 0;
                   
$data[ $staffId ]['rating_average'] = 0;
                }
            }
           
           
/* Get their replies */
           
$where = array( array( \IPS\Db::i()->in( 'reply_member', array_keys( $data ) ) ) );
            if ( isset( \
IPS\Request::i()->filter ) and array_key_exists( \IPS\Request::i()->filter, $filters ) )
            {
               
$where[] = array( 'reply_date>?', $filters[ \IPS\Request::i()->filter ] );
            }
            foreach ( \
IPS\Db::i()->select( 'COUNT(*) AS count, reply_member', 'nexus_support_replies', $where, NULL, NULL, 'reply_member' ) as $row )
            {
               
$data[ $row['reply_member'] ]['reply_count'] = $row['count'];
            }
           
           
/* And their ratings */
           
if ( \IPS\Settings::i()->nexus_support_satisfaction )
            {
               
$where = array( \IPS\Db::i()->in( 'rating_staff', array_keys( $data ) ) );
                if ( isset( \
IPS\Request::i()->filter ) and array_key_exists( \IPS\Request::i()->filter, $filters ) )
                {
                   
$where[] = array( 'rating_date>?', $filters[ \IPS\Request::i()->filter ] );
                }
                foreach ( \
IPS\Db::i()->select( 'COUNT(*) AS count, AVG(rating_rating) AS rating, rating_staff', 'nexus_support_ratings', $where, NULL, NULL, 'rating_staff' ) as $row )
                {
                   
$data[ $row['rating_staff'] ]['rating_count'] = $row['count'];
                   
$data[ $row['rating_staff'] ]['rating_average'] = $row['rating'];
                }
            }
                       
           
/* Build the table */
           
$staffProductivityTable = new \IPS\Helpers\Table\Custom( $data, \IPS\Http\Url::internal( 'app=nexus&module=support&controller=reports&tab=overview' ) );
           
$staffProductivityTable->langPrefix = 'staff_';
           
$staffProductivityTable->widths = \IPS\Settings::i()->nexus_support_satisfaction ? array( 'name' => 50, 'reply_count' => 25, 'rating_average' => 25 ) : array( 'name' => 75, 'reply_count' => 25 );
            if ( \
IPS\Settings::i()->nexus_support_satisfaction )
            {
               
$staffProductivityTable->parsers['rating_average'] = function( $val, $row ) {
                    return \
IPS\Theme::i()->getTemplate('supportreports')->averageRatingCell( $val, $row['rating_count'] );
                };
               
$staffProductivityTable->include = array( 'name', 'reply_count', 'rating_average' );
            }
           
$staffProductivityTable->sortBy = $staffProductivityTable->sortBy ?: 'reply_count';
           
$staffProductivityTable->quickSearch = 'name';
           
           
/* Specify the filters and search options */
           
$staffProductivityTable->filters = $filters;
   
           
/* Buttons for each member */
           
$staffProductivityTable->rowButtons = function( $row, $id )
            {
                return array(
                   
'report'    => array(
                       
'icon'        => 'search',
                       
'title'        => 'view_report',
                       
'link'        => \IPS\Http\Url::internal('app=nexus&module=support&controller=reports&do=staff')->setQueryString( 'id', $id ),
                    ),
                );    
            };
           
           
/* Output */
           
$activeTabContents = (string) $staffProductivityTable;
        }
       
       
/* Replies */
       
elseif ( $activeTab === 'replies' )
        {
           
$staffRepliesChart    = new \IPS\Helpers\Chart\Database( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=reports&tab=replies' ), 'nexus_support_replies', 'reply_date', '',
                array(
                   
'vAxis'        => array( 'title' => \IPS\Member::loggedIn()->language()->addToStack('replies_made') ),
                   
'height'    => 700,
                   
'backgroundColor'     => '#ffffff',
                   
'colors'            => array( '#10967e', '#ea7963', '#de6470', '#6b9dde', '#b09be4', '#eec766', '#9fc973', '#e291bf', '#55c1a6', '#5fb9da' ),
                   
'hAxis'                => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
                   
'lineWidth'            => 1,
                   
'areaOpacity'        => 0.4
               
),
               
'AreaChart', 'daily', array( 'start' => \IPS\DateTime::create()->sub( new \DateInterval( 'P1M' ) ), 'end' => 0 )
            );
           
$staffRepliesChart->where[] = array( 'reply_type=?', \IPS\nexus\Support\Reply::REPLY_STAFF );
           
$staffRepliesChart->groupBy    = 'reply_member';
            foreach( \
IPS\nexus\Support\Request::staff() as $id => $name )
            {
               
$staffRepliesChart->addSeries( $name, 'number', 'COUNT(*)', TRUE, $id );
            }
           
           
$activeTabContents = (string) $staffRepliesChart;
        }
       
       
/* Replies */
       
elseif ( $activeTab === 'feedback_ratings' )
        {
           
$staffRatingsChart    = new \IPS\Helpers\Chart\Database( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=reports&tab=feedback_ratings' ), 'nexus_support_ratings', 'rating_date', '',
                array(
                   
'vAxis'        => array( 'title' => \IPS\Member::loggedIn()->language()->addToStack('average_rating'), 'viewWindow' => array( 'min' => 0, 'max' => 5 ) ),
                   
'height'    => 700,
                   
'backgroundColor'     => '#ffffff',
                   
'colors'            => array( '#10967e', '#ea7963', '#de6470', '#6b9dde', '#b09be4', '#eec766', '#9fc973', '#e291bf', '#55c1a6', '#5fb9da' ),
                   
'hAxis'                => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
                   
'lineWidth'            => 1,
                   
'areaOpacity'        => 0.4
               
),
               
'ColumnChart', 'monthly', array( 'start' => \IPS\DateTime::create()->sub( new \DateInterval( 'P1M' ) ), 'end' => \IPS\DateTime::create() )
            );
           
$staffRatingsChart->plotZeros = FALSE;
           
$staffRatingsChart->groupBy    = 'rating_staff';
            foreach( \
IPS\nexus\Support\Request::staff() as $id => $name )
            {
               
$staffRatingsChart->addSeries( $name, 'number', 'AVG(rating_rating)', TRUE, $id );
            }
           
           
$activeTabContents = (string) $staffRatingsChart;
        }
       
       
/* Latest Feedback */
       
elseif ( $activeTab === 'latest_feedback' )
        {
           
$table = new \IPS\Helpers\Table\Db( 'nexus_support_ratings', \IPS\Http\Url::internal('app=nexus&module=support&controller=reports&tab=latest_feedback') );
           
$table->joins = array(
                array(
                   
'from'        => 'nexus_support_replies',
                   
'where'        => 'reply_id=rating_reply'
               
),
                array(
                   
'from'        => 'nexus_support_requests',
                   
'where'        => 'r_id=reply_request'
               
)
            );
           
$table->sortBy = 'rating_date';
           
$table->sortDirection = 'desc';
           
$table->parsers = array(
               
'reply_post'    => function( $val )
                {
                    return
$val;
                }
            );
           
           
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate('support'), 'latestFeedback' );
           
           
$activeTabContents = (string) $table;
        }
                                       
       
/* Display */
       
if ( \IPS\Request::i()->isAjax() )
        {
            \
IPS\Output::i()->output = $activeTabContents;
        }
        else
        {
            \
IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('performance_reports');
            \
IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $activeTab, $activeTabContents, \IPS\Http\Url::internal( "app=nexus&module=support&controller=reports" ) );
        }
    }
   
   
/**
     * Staff Report
     *
     * @return    void
     */
   
protected function staff()
    {
       
/* Load */
       
$id = \IPS\Request::i()->id;
        if ( !
array_key_exists( $id, \IPS\nexus\Support\Request::staff() ) )
        {
            \
IPS\Output::i()->error( 'node_error', '2X207/1', 404, '' );
        }
       
$staff = \IPS\Member::load( $id );
       
       
/* Tabs */
       
$tabs = array(
           
'productivity'         => 'productivity',
           
'latest_replies'    => 'latest_replies',
           
'feedback_ratings'    => 'feedback_ratings',
           
'latest_feedback'    => 'latest_feedback'
       
);
       
$activeTab = ( isset( \IPS\Request::i()->tab ) and array_key_exists( \IPS\Request::i()->tab, $tabs ) ) ? \IPS\Request::i()->tab : 'productivity';
       
$activeTabContents = '';
       
       
/* Daily Productivity */
       
if ( $activeTab === 'productivity' )
        {            
           
/* Date Range */
           
$where = array( array( 'reply_type=?', \IPS\nexus\Support\Reply::REPLY_STAFF ) );
           
$timeframe = isset( \IPS\Request::i()->timeframe ) ? \IPS\Request::i()->timeframe : 'last_30_days';
            switch (
$timeframe )
            {
                case
'last_24_hours':
                   
$daysInTimeframe = 1;
                    break;
                case
'last_7_days':
                   
$daysInTimeframe = 7;
                    break;
                case
'last_30_days':
                   
$daysInTimeframe = 30;
                    break;
            }
           
$where[] = array( 'reply_date>?', \IPS\DateTime::ts( time() )->sub( new \DateInterval( "P{$daysInTimeframe}D" ) )->getTimestamp() );
                       
           
/* Init */
           
$numberOfStaffMembers = \IPS\Db::i()->select( 'COUNT(DISTINCT reply_member)', 'nexus_support_replies', $where )->first();
           
$now = \IPS\DateTime::ts( time() );
           
$myOffset = $now->getTimezone()->getOffset( $now ) / 3600;
           
           
/* Group */
           
$span = isset( \IPS\Request::i()->span ) ? \IPS\Request::i()->span : 'day';
           
$group = $span === 'day' ? '%H' : '%w';
           
           
/* Type */
           
$type = isset( \IPS\Request::i()->type ) ? \IPS\Request::i()->type : 'total';
           
           
/* Get average replies by hour for this staff member */
           
$thisStaffMember = array();
           
$thisStaffMemberCount = array();
            foreach( \
IPS\Db::i()->select( "COUNT(*) AS count, reply_date AS unixtime, DATE_FORMAT( FROM_UNIXTIME( reply_date ), '{$group}' ) AS hour", 'nexus_support_replies', array_merge( $where, array( array( 'reply_member=?', $staff->member_id ) ) ), NULL, NULL, array( 'hour', 'reply_date' ) ) as $row )
            {            
               
$_group = $span === 'day' ? \IPS\DateTime::ts( $row['unixtime'] )->format('G') : \IPS\DateTime::ts( $row['unixtime'] )->format('w');
               
                if ( !isset(
$thisStaffMemberCount[ $_group ] ) )
                {
                   
$thisStaffMemberCount[ $_group ] = 0;
                }
               
               
$thisStaffMemberCount[ $_group ] = $thisStaffMemberCount[ $_group ] + $row['count'];
            }
           
            foreach(
$thisStaffMemberCount AS $_group => $count )
            {
               
$thisStaffMember[ $_group ] = round( ( $type === 'average' ) ? ( $count / $daysInTimeframe ) : $count, 1 );
            }
           
           
/* Get average replies by hour for all staff members */
           
if ( $numberOfStaffMembers > 1 )
            {
               
$allStaffMembers = array();
               
$allStaffMembersCount = array();
                foreach( \
IPS\Db::i()->select( "COUNT(*) AS count, reply_date AS unixtime, DATE_FORMAT( FROM_UNIXTIME( reply_date ), '{$group}' ) AS hour", 'nexus_support_replies', $where, NULL, NULL, array( 'hour', 'reply_date' ) ) as $row )
                {
                   
$_group = $span === 'day' ? \IPS\DateTime::ts( $row['unixtime'] )->format('G') : \IPS\DateTime::ts( $row['unixtime'] )->format('w');
                   
                    if ( !isset(
$allStaffMembersCount[ $_group ] ) )
                    {
                       
$allStaffMembersCount[ $_group ] = 0;
                    }
                   
                   
$allStaffMembersCount[ $_group ] = $allStaffMembersCount[ $_group ] + $row['count'];
                }
               
                foreach(
$allStaffMembersCount AS $_group => $count )
                {
                   
$allStaffMembers[ $_group ] = round( ( ( $type === 'average' ) ? ( $count / $daysInTimeframe ) : $count ) / $numberOfStaffMembers, 1 );
                }
            }
                                       
           
/* Build Chart */
           
$chart = new \IPS\Helpers\Chart;
           
$chart->addHeader( \IPS\Member::loggedIn()->language()->addToStack('hour'), 'string' );
           
$chart->addHeader( $staff->name, 'number' );
            if (
$numberOfStaffMembers > 1 )
            {
               
$chart->addHeader( \IPS\Member::loggedIn()->language()->addToStack('all_staff_average'), 'number' );
            }
            if (
$span === 'day' )
            {
                foreach (
range( 0 - $myOffset, 23 - $myOffset ) as $hour )
                {
                   
$timestamp = mktime( 0, 0, 0 ) + ( $hour * 3600 );
                                                   
                    if (
$numberOfStaffMembers > 1 )
                    {                
                       
$chart->addRow( array(
                            \
IPS\DateTime::ts( $timestamp )->localeTime( FALSE, FALSE ),
                            isset(
$thisStaffMember[ $hour + $myOffset ] ) ? $thisStaffMember[ $hour + $myOffset ] : 0,
                            isset(
$allStaffMembers[ $hour + $myOffset ] ) ? $allStaffMembers[ $hour + $myOffset ] : 0
                       
) );
                    }
                    else
                    {
                       
$chart->addRow( array(
                            \
IPS\DateTime::ts( $timestamp )->localeTime( FALSE, FALSE ),
                            isset(
$thisStaffMember[ $hour + $myOffset ] ) ? $thisStaffMember[ $hour + $myOffset ] : 0
                       
) );
                    }
                }
            }
            else
            {
                foreach (
range( 0, 6 ) as $day )
                {
                    if (
$numberOfStaffMembers > 1 )
                    {                
                       
$chart->addRow( array(
                            \
IPS\Member::loggedIn()->language()->addToStack("weekday_{$day}"),
                            isset(
$thisStaffMember[ $day ] ) ? $thisStaffMember[ $day ] : 0,
                            isset(
$allStaffMembers[ $day ] ) ? $allStaffMembers[ $day ] : 0
                       
) );
                    }
                    else
                    {
                       
$chart->addRow( array(
                            \
IPS\Member::loggedIn()->language()->addToStack("weekday_{$day}"),
                            isset(
$thisStaffMember[ $day ] ) ? $thisStaffMember[ $day ] : 0
                       
) );
                    }
                }
            }
           
           
/* Display */
           
$activeTabContents = \IPS\Theme::i()->getTemplate('supportreports')->timeChart(
               
$chart->render( 'SteppedAreaChart', array(
                   
'legend'             => array( 'position' => 'none' ),
                     
'areaOpacity'        => 0.4,
                     
'lineWidth'            => 1,
                     
'backgroundColor'     => '#ffffff',
                     
'colors'            => array( '#10967e' ),
                     
'hAxis'                => array( 'gridlines' => array( 'color' => '#f5f5f5' ) ),
                ) ),
                \
IPS\Http\Url::internal( "app=nexus&module=support&controller=reports&do=staff&id={$staff->member_id}&tab=productivity" )->setQueryString( array(
                   
'span'        => $span,
                   
'timeframe'    => $timeframe,
                   
'type'        => $type
               
) )
            );
        }
       
       
/* Latest Replies */
       
elseif ( $activeTab === 'latest_replies' )
        {
            \
IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'support.css', 'nexus', 'admin' ) );
           
$table = new \IPS\Helpers\Table\Content( 'IPS\nexus\Support\Reply', \IPS\Http\Url::internal( "app=nexus&module=support&controller=reports&do=staff&id={$staff->member_id}&tab=latest_replies" ), array( array( 'reply_type=? AND reply_member=?', \IPS\nexus\Support\Reply::REPLY_STAFF, $staff->member_id ) ) );
           
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'tables', 'core', 'front' ), 'table' );
           
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'supportreports' ), 'supportReplyRows' );
           
$table->sortBy = 'reply_date';
           
$activeTabContents = (string) $table;
        }
       
       
/* Feedback */
       
elseif ( $activeTab === 'feedback_ratings' )
        {
           
$staffRatingsChart    = new \IPS\Helpers\Chart\Database( \IPS\Http\Url::internal( "app=nexus&module=support&controller=reports&do=staff&id={$staff->member_id}&tab=feedback_ratings" ), 'nexus_support_ratings', 'rating_date', '',
                array(
                   
'vAxis'        => array( 'title' => \IPS\Member::loggedIn()->language()->addToStack('average_rating'), 'viewWindow' => array( 'min' => 0, 'max' => 5 ) ),
                   
'legend'    => 'none'
               
),
               
'LineChart', 'monthly'
           
);
           
$staffRatingsChart->plotZeros = FALSE;
           
$staffRatingsChart->addSeries( $staff->name, 'number', 'AVG(rating_rating)', FALSE );
           
           
$activeTabContents = (string) $staffRatingsChart;
        }
       
       
/* Latest Feedback */
       
elseif ( $activeTab === 'latest_feedback' )
        {
           
$table = new \IPS\Helpers\Table\Db( 'nexus_support_ratings', \IPS\Http\Url::internal("app=nexus&module=support&controller=reports&do=staff&id={$staff->member_id}&tab=latest_feedback"), array( 'rating_staff=?', $staff->member_id ) );
           
$table->joins = array(
                array(
                   
'from'        => 'nexus_support_replies',
                   
'where'        => 'reply_id=rating_reply'
               
),
                array(
                   
'from'        => 'nexus_support_requests',
                   
'where'        => 'r_id=reply_request'
               
)
            );
           
$table->sortBy = 'rating_date';
           
$table->sortDirection = 'desc';
           
$table->parsers = array(
               
'reply_post'    => function( $val )
                {
                    return
$val;
                }
            );
           
           
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate('support'), 'latestFeedback' );
           
           
$activeTabContents = (string) $table;
        }
       
       
/* Display */
       
if ( \IPS\Request::i()->isAjax() )
        {
            \
IPS\Output::i()->output = $activeTabContents;
        }
        else
        {
            \
IPS\Output::i()->title = $staff->name;
            \
IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $activeTab, $activeTabContents, \IPS\Http\Url::internal( "app=nexus&module=support&controller=reports&do=staff&id={$staff->member_id}" ) );
        }
    }
}