Version 4.0.13.1

This commit is contained in:
Neo committed 2025-12-19 04:57:54 -08:00
1 parent f9e857d255
commit c6a86f0d9b
7517 files changed
+597400 -668041

No files matched your search

@@ -0,0 +1,68 @@
<?php
/**
* @brief Autoresolve Settings
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 25 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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;
}
/**
* Autoresolve Settings
*/
class _autoresolve extends \IPS\Dispatcher\Controller
{
/**
* Manage
*
* @return void
*/
protected function manage()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'autoresolve_manage' );
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\YesNo( 'nexus_autoresolve_on', \IPS\Settings::i()->nexus_autoresolve_days, FALSE, array( 'togglesOn' => array( 'nexus_autoresolve_departments', 'nexus_autoresolve_applicable', 'nexus_autoresolve_days', 'nexus_autoresolve_notify', 'nexus_autoresolve_status' ) ) ) );
$form->addSeparator();
$form->add( new \IPS\Helpers\Form\Node( 'nexus_autoresolve_departments', \IPS\Settings::i()->nexus_autoresolve_departments === '*' ? 0 : explode( ',', \IPS\Settings::i()->nexus_autoresolve_departments ), FALSE, array( 'class' => 'IPS\nexus\Support\Department', 'multiple' => TRUE, 'zeroVal' => 'any' ), NULL, NULL, NULL, 'nexus_autoresolve_departments' ) );
$form->add( new \IPS\Helpers\Form\Node( 'nexus_autoresolve_applicable', \IPS\Settings::i()->nexus_autoresolve_applicable, FALSE, array( 'class' => 'IPS\nexus\Support\Status', 'multiple' => TRUE ), NULL, NULL, NULL, 'nexus_autoresolve_applicable' ) );
$form->add( new \IPS\Helpers\Form\Number( 'nexus_autoresolve_days', \IPS\Settings::i()->nexus_autoresolve_days, FALSE, array(), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('days'), 'nexus_autoresolve_days' ) );
$form->add( new \IPS\Helpers\Form\Node( 'nexus_autoresolve_status', \IPS\Settings::i()->nexus_autoresolve_status, FALSE, array( 'class' => 'IPS\nexus\Support\Status' ), NULL, NULL, NULL, 'nexus_autoresolve_status' ) );
$form->add( new \IPS\Helpers\Form\Number( 'nexus_autoresolve_notify', \IPS\Settings::i()->nexus_autoresolve_notify, FALSE, array( 'unlimited' => 0, 'unlimitedLang' => 'never' ), NULL, NULL, \IPS\Member::loggedIn()->language()->addToStack('hours_before_resolving'), 'nexus_autoresolve_notify' ) );
if ( $values = $form->values() )
{
\IPS\DB::i()->update( 'core_tasks', array( 'enabled' => (int) $values['nexus_autoresolve_on'] ), "`key`='supportAutoresolve'" );
if ( !$values['nexus_autoresolve_on'] )
{
$values['nexus_autoresolve_days'] = 0;
}
unset( $values['nexus_autoresolve_on'] );
$values['nexus_autoresolve_departments'] = $values['nexus_autoresolve_departments'] ? implode( ',' , array_keys( $values['nexus_autoresolve_departments'] ) ) : '*';
$values['nexus_autoresolve_applicable'] = implode( ',', array_keys( $values['nexus_autoresolve_applicable'] ) );
$values['nexus_autoresolve_status'] = $values['nexus_autoresolve_status']->id;
$form->saveAsSettings( $values );
\IPS\Session::i()->log( 'acplogs__autoresolve_settings' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=settings&tab=autoresolve') );
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('autoresolve');
\IPS\Output::i()->output = $form;
}
}
@@ -0,0 +1,48 @@
<?php
/**
* @brief Customer Feedback Settings
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 23 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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;
}
/**
* Customer Feedback Settings
*/
class _customerfeedback extends \IPS\Dispatcher\Controller
{
/**
* Manage
*
* @return void
*/
protected function manage()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'customerfeedback_manage' );
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\YesNo( 'nexus_support_satisfaction', \IPS\Settings::i()->nexus_support_satisfaction ) );
if ( $form->values() )
{
$form->saveAsSettings();
\IPS\Session::i()->log( 'acplogs__customerfeedback_settings' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=settings&tab=customerfeedback' ), 'saved' );
}
\IPS\Output::i()->output = $form;
}
}
@@ -0,0 +1,76 @@
<?php
/**
* @brief Support Departments
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 08 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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 Departments
*/
class _departments extends \IPS\Node\Controller
{
/**
* Node Class
*/
protected $nodeClass = 'IPS\nexus\Support\Department';
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'departments_manage' );
parent::execute();
}
/**
* Delete
*
* @return void
*/
protected function delete()
{
try
{
$node = \IPS\nexus\Support\Department::load( \IPS\Request::i()->id );
if ( $node->canDelete() and \IPS\Db::i()->select( 'COUNT(*)', 'nexus_support_requests', array( 'r_department=?', $node->id ) ) )
{
$form = new \IPS\Helpers\Form( 'delete', 'delete' );
$form->add( new \IPS\Helpers\Form\Node( 'move_existing_requests_to', NULL, TRUE, array( 'class' => 'IPS\nexus\Support\Department', 'permissionCheck' => function( $_node ) use ( $node )
{
return $node->id != $_node->id;
} ) ) );
if ( $values = $form->values() )
{
\IPS\Db::i()->update( 'nexus_support_requests', array( 'r_department' => $values['move_existing_requests_to']->id ), array( 'r_department=?', $node->id ) );
\IPS\Request::i()->form_submitted = TRUE;
return parent::delete();
}
\IPS\Output::i()->output = $form;
return;
}
}
catch ( \OutOfRangeException $e ){}
return parent::delete();
}
}
@@ -0,0 +1,42 @@
<?php
/**
* @brief Support Custom Fields
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 16 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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 Custom Fields
*/
class _fields extends \IPS\Node\Controller
{
/**
* Node Class
*/
protected $nodeClass = 'IPS\nexus\Support\CustomField';
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'scfields_manage' );
parent::execute();
}
}
@@ -0,0 +1,251 @@
<?php
/**
* @brief Incoming Email Setup
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 16 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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;
}
/**
* Incoming Email
*/
class _incomingemail extends \IPS\Dispatcher\Controller
{
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'incomingemail_manage' );
parent::execute();
}
/**
* Manage
*
* @return void
*/
protected function manage()
{
$table = new \IPS\Helpers\Table\Db( 'core_incoming_emails', \IPS\Http\Url::internal( 'app=nexus&module=support&controller=settings&tab=incomingemail' ) );
$table->include = array( 'rule_criteria_value' );
$table->noSort = array( 'rule_criteria_value' );
$table->parsers = array(
'rule_criteria_value' => function( $val, $row )
{
$_langCf = 'ie_cf_' . $row['rule_criteria_field'];
$_langCt = 'ie_ct_' . $row['rule_criteria_type'];
return \IPS\Member::loggedIn()->language()->addToStack( $_langCf ) . ' ' . \IPS\Member::loggedIn()->language()->addToStack( $_langCt ) . ' "' . $val . '"';
}
);
$table->sortBy = $table->sortBy ?: 'rule_added_date';
$table->sortDirection = $table->sortDirection ?: 'asc';
$table->rootButtons = array(
'add' => array(
'icon' => 'plus',
'title' => 'incomingemail_add',
'link' => \IPS\Http\Url::internal( 'app=nexus&module=support&controller=settings&tab=incomingemail&do=incomingEmailForm' ),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('incomingemail_add') )
)
);
$table->rowButtons = function( $row )
{
return array(
'edit' => array(
'icon' => 'pencil',
'title' => 'edit',
'link' => \IPS\Http\Url::internal( 'app=nexus&module=support&controller=settings&tab=incomingemail&do=incomingEmailForm&id=' ) . $row['rule_id'],
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('edit') )
),
'delete' => array(
'icon' => 'times-circle',
'title' => 'delete',
'link' => \IPS\Http\Url::internal( 'app=nexus&module=support&controller=settings&tab=incomingemail&do=incomingEmailDelete&id=' ) . $row['rule_id'],
'data' => array( 'delete' => '' ),
)
);
};
if ( isset( \IPS\Request::i()->type ) )
{
if ( \IPS\Request::i()->type === 'piping' )
{
$content = \IPS\Theme::i()->getTemplate('incomingemailsetup')->piping();
}
elseif ( \IPS\Request::i()->type === 'pop3' )
{
$content = \IPS\Theme::i()->getTemplate('incomingemailsetup')->pop3( $this->_pop3() );
}
else
{
$content = \IPS\Theme::i()->getTemplate('incomingemailsetup')->splash( (string) $table );
}
}
else
{
$content = NULL;
if ( \IPS\Settings::i()->pop3_server )
{
try
{
$task = \IPS\Db::i()->select( '*', 'core_tasks', array( 'app=? AND `key`=? AND enabled=1', 'core', 'pop' ) )->first();
$pop3Form = $this->_pop3();
$pop3Form->addButton( 'disable_pop3', 'link', \IPS\Http\Url::internal( 'app=nexus&module=support&controller=incomingemail&do=disablePop3' ), '', array( 'data-confirm' => '' ) );
$content = \IPS\Theme::i()->getTemplate('incomingemailsetup')->usingpop3( $pop3Form, (string) $table );
}
catch ( \UnderflowException $e ) { }
}
$content = $content ?: \IPS\Theme::i()->getTemplate('incomingemailsetup')->splash( (string) $table );
}
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_support.js', 'nexus', 'admin' ) );
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('incomingemailsetup')->template( $content );
}
/**
* Disable POP3
*
* @return void
*/
protected function disablePop3()
{
\IPS\Session::i()->log( 'acplogs__pop3_settings' );
\IPS\DB::i()->update( 'core_tasks', array( 'enabled' => 0 ), array( 'app=? AND `key`=?', 'core', 'pop' ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=settings&tab=incomingemail') );
}
/**
* POP3
*
* @return \IPS\Helpers\Form
*/
protected function _pop3()
{
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Text( 'pop3_server', \IPS\Settings::i()->pop3_server, TRUE ) );
$form->add( new \IPS\Helpers\Form\Number( 'pop3_port', \IPS\Settings::i()->pop3_port, TRUE ) );
$form->add( new \IPS\Helpers\Form\Text( 'pop3_user', \IPS\Settings::i()->pop3_user, TRUE ) );
$form->add( new \IPS\Helpers\Form\Text( 'pop3_password', \IPS\Settings::i()->pop3_password, FALSE ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'pop3_tls', \IPS\Settings::i()->pop3_tls ) );
if ( $values = $form->values() )
{
require_once \IPS\ROOT_PATH . '/system/3rd_party/pop3/pop3.class.inc';
$pop3 = new \POP3;
try
{
if ( !$pop3->connect( ( $values['pop3_tls'] ? 'ssl://' : '' ) . $values['pop3_server'], $values['pop3_port'] ) )
{
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack('pop3_connect_err') );
}
if ( !$pop3->login( $values['pop3_user'], $values['pop3_password'] ) )
{
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack('pop3_login_err') );
}
$form->saveAsSettings();
\IPS\Session::i()->log( 'acplogs__pop3_settings' );
\IPS\DB::i()->update( 'core_tasks', array( 'enabled' => 1 ), array( 'app=? AND `key`=?', 'core', 'pop' ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=settings&tab=incomingemail') );
}
catch ( \Exception $e )
{
$form->error = $e->getMessage();
}
}
return $form;
}
/**
* Add/Edit Incoming Email Rule Form
*
* @return void
*/
protected function incomingEmailForm()
{
/* Load Rule */
$rule = NULL;
if ( \IPS\Request::i()->id )
{
try
{
$rule = \IPS\Db::i()->select( '*', 'core_incoming_emails', array( 'rule_id=?', \IPS\Request::i()->id ) )->first();
}
catch ( \UnderflowException $e ) { }
}
/* Build form */
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Custom( 'rule_criteria_value', array(
'criteria_field' => $rule ? $rule['rule_criteria_field'] : '',
'criteria_type' => $rule ? $rule['rule_criteria_type'] : '',
'criteria_value' => $rule ? $rule['rule_criteria_value'] : ''
), FALSE, array( 'getHtml' => function( $element )
{
return \IPS\Theme::i()->getTemplate( 'advancedsettings', 'core' )->ruleCriteriaForm( $element->name, $element->defaultValue['criteria_field'], $element->defaultValue['criteria_type'], $element->defaultValue['criteria_value'] );
} ) ) );
/* Handle submissions */
if ( $values = $form->values() )
{
$save = array(
'rule_criteria_field' => $values['rule_criteria_value']['criteria_field'],
'rule_criteria_type' => $values['rule_criteria_value']['criteria_type'],
'rule_criteria_value' => $values['rule_criteria_value']['criteria_value'],
'rule_app' => '',
);
if ( $rule )
{
\IPS\Db::i()->update( 'core_incoming_emails', $save, array( 'rule_id=?', $rule['rule_id'] ) );
\IPS\Session::i()->log( 'acplogs__incomingemail_edited' );
}
else
{
$save['rule_added_date'] = time();
$save['rule_added_by'] = \IPS\Member::loggedIn()->member_id;
\IPS\Db::i()->insert( 'core_incoming_emails', $save );
\IPS\Session::i()->log( 'acplogs__incomingemail_added' );
}
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=settings&tab=incomingemail&tab=incomingemail' ), 'saved' );
}
/* Display */
\IPS\Output::i()->output = $form;
}
/**
* Delete Incoming Email Rule
*
* @return void
*/
protected function incomingEmailDelete()
{
\IPS\Db::i()->delete( 'core_incoming_emails', array( 'rule_id=?', \IPS\Request::i()->id ) );
\IPS\Session::i()->log( 'acplogs__incomingemail_deleted' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=nexus&module=support&controller=settings&tab=incomingemail&tab=incomingemail" ) );
}
}
Whitespace-only changes.
@@ -0,0 +1,73 @@
<?php
/**
* @brief Outgoing Email Settings
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 18 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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;
}
/**
* Outgoing Email Settings
*/
class _outgoingemail extends \IPS\Dispatcher\Controller
{
/**
* Manage
*
* @return void
*/
protected function manage()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'autoresolve_manage' );
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Radio( 'nexus_sout_chrome', \IPS\Settings::i()->nexus_sout_chrome, FALSE, array(
'options' => array(
0 => \IPS\Theme::i()->resource( 'settings/email_no_chrome.png' ),
1 => \IPS\Theme::i()->resource( 'settings/email_chrome.png' )
),
'parse' => 'image',
'descriptions' => array(
0 => \IPS\Member::loggedIn()->language()->addToStack('nexus_sout_chrome_no'),
1 => \IPS\Member::loggedIn()->language()->addToStack('nexus_sout_chrome_yes'),
)
) ) );
$form->add( new \IPS\Helpers\Form\Radio( 'nexus_sout_from', \IPS\Settings::i()->nexus_sout_from, FALSE, array(
'options' => array(
'staff' => 'nexus_sout_from_staff',
'dpt' => 'nexus_sout_from_department',
'other' => 'nexus_sout_from_other',
),
'userSuppliedInput' => 'other',
'toggles' => array(
'other' => array( 'other_nexus_sout_from' )
)
) ) );
$form->add( new \IPS\Helpers\Form\YesNo( 'nexus_sout_autoreply', \IPS\Settings::i()->nexus_sout_autoreply ) );
if ( $form->values() )
{
$form->saveAsSettings();
\IPS\Session::i()->log( 'acplogs__outgoingemail_settings' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=settings&tab=outgoingemail' ), 'saved' );
}
\IPS\Output::i()->output = $form;
}
}
@@ -0,0 +1,399 @@
<?php
/**
* @brief Support Reports
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 23 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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' => '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' )
{
/* Build table */
$staffProductivityTable = new \IPS\Helpers\Table\Db(
'nexus_support_replies',
\IPS\Http\Url::internal( 'app=nexus&module=support&controller=reports&act=productivity_table' ),
array(
array( 'reply_type=?', \IPS\nexus\Support\Reply::REPLY_STAFF ),
\IPS\Db::i()->in( 'reply_member', array_keys( \IPS\nexus\Support\Request::staff() ) )
),
'reply_member'
);
$staffProductivityTable->langPrefix = 'staff_';
$staffProductivityTable->selects = array( 'COUNT(*) AS reply_count' );
$staffProductivityTable->include = array( 'name', 'reply_count' );
$staffProductivityTable->widths = array( 'name' => 75, 'reply_count' => 25 );
$staffProductivityTable->parsers['reply_count'] = function( $val ) { return intval( $val ); };
if ( \IPS\Settings::i()->nexus_support_satisfaction )
{
$staffProductivityTable->joins[] = array(
'select' => 'rating_count, rating_average',
'from' => \IPS\Db::i()->select( 'rating_reply, COUNT(*) AS rating_count, AVG(rating_rating) AS rating_average', 'nexus_support_ratings' ),
'where' => 'rating_reply=reply_id'
);
$staffProductivityTable->include[] = 'rating_average';
$staffProductivityTable->widths = array( 'name' => 50, 'reply_count' => 25, 'rating_average' => 25 );
$staffProductivityTable->parsers['rating_average'] = function( $val, $row ) {
return \IPS\Theme::i()->getTemplate('supportreports')->averageRatingCell( $val, $row['rating_count'] );
};
}
$staffProductivityTable->sortBy = $staffProductivityTable->sortBy ?: 'reply_count';
/* We need to join the members table for the name */
$staffProductivityTable->joins[] = array(
'select' => 'name',
'from' => 'core_members',
'where' => 'member_id=reply_member'
);
$staffProductivityTable->quickSearch = 'name';
/* Specify the filters and search options */
$staffProductivityTable->filters = array(
'last_24_hours' => array( 'reply_date>?', \IPS\DateTime::create()->sub( new \DateInterval( 'P1D' ) )->getTimestamp() ),
'last_7_days' => array( 'reply_date>?', \IPS\DateTime::create()->sub( new \DateInterval( 'P7D' ) )->getTimestamp() ),
'last_30_days' => array( 'reply_date>?', \IPS\DateTime::create()->sub( new \DateInterval( 'P30D' ) )->getTimestamp() ),
);
/* Buttons for each member */
$staffProductivityTable->rowButtons = function( $row )
{
return array(
'report' => array(
'icon' => 'search',
'title' => 'view_report',
'link' => \IPS\Http\Url::internal('app=nexus&module=support&controller=reports&do=staff')->setQueryString( 'id', $row['reply_member'] ),
),
);
};
$activeTabContents = (string) $staffProductivityTable;
}
/* Replies */
elseif ( $activeTab === 'replies' )
{
$staffRepliesChart = new \IPS\Helpers\Chart\Dynamic( \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') ),
),
'LineChart', '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\Dynamic( \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 ) ),
),
'ColumnChart', 'monthly'
);
$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();
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, 'hour' ) as $row )
{
$_group = $span === 'day' ? \IPS\DateTime::ts( $row['unixtime'] )->format('G') : \IPS\DateTime::ts( $row['unixtime'] )->format('w');
$thisStaffMember[ $_group ] = round( ( $type === 'average' ) ? ( $row['count'] / $daysInTimeframe ) : $row['count'], 1 );
}
/* Get average replies by hour for all staff members */
if ( $numberOfStaffMembers > 1 )
{
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, 'hour' ) as $row )
{
$_group = $span === 'day' ? \IPS\DateTime::ts( $row['unixtime'] )->format('G') : \IPS\DateTime::ts( $row['unixtime'] )->format('w');
$allStaffMembers[ $_group ] = round( ( ( $type === 'average' ) ? ( $row['count'] / $daysInTimeframe ) : $row['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( 'ColumnChart' ), \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\Dynamic( \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}" ) );
}
}
}
@@ -0,0 +1,748 @@
<?php
/**
* @brief Support Request View
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 09 Apr 2014
* @version SVN_VERSION_NUMBER
*/
namespace IPS\nexus\modules\admin\support;
use \IPS\nexus\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 Request View
*/
class _request extends \IPS\nexus\modules\front\support\view
{
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'requests_manage' );
parent::execute();
}
/**
* View Item
*
* @return void
*/
protected function manage()
{
\IPS\Output::i()->breadcrumb[] = array( \IPS\Http\Url::internal('app=nexus&module=support&controller=requests'), \IPS\Member::loggedIn()->language()->addToStack('menu__nexus_support_requests') );
parent::manage();
/* AJAX responders */
if ( \IPS\Request::i()->isAjax() )
{
/* Popup which has the merge button */
if ( isset( \IPS\Request::i()->popup ) )
{
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->requestPopup( $this->request );
}
/* Stock Action data */
elseif( isset( \IPS\Request::i()->stockActionData ) )
{
if ( \IPS\Request::i()->stockActionData )
{
try
{
$action = \IPS\nexus\Support\StockAction::load( \IPS\Request::i()->stockActionData );
$data = array();
if ( $action->department )
{
$data['department'] = $action->department->id;
}
else
{
$data['department'] = $this->request->department->id;
}
if ( $action->status )
{
$data['status'] = $action->status->id;
}
else
{
$data['status'] = \IPS\nexus\Support\Status::load( TRUE, 'status_default_staff' )->id;
}
if ( $action->staff )
{
$data['assign_to'] = $action->staff->member_id;
}
else
{
$data['assign_to'] = $this->request->staff_lock ? ( $this->request->staff ? $this->request->staff->member_id : 0 ) : 0;
}
if ( $action->message )
{
$data['message'] = $action->message;
}
\IPS\Output::i()->json( $data );
}
catch ( \Exception $e )
{
\IPS\Output::i()->json( $e->getMessage(), 500 );
}
}
else
{
\IPS\Output::i()->json( array(
'department' => $this->request->department->id,
'status' => \IPS\nexus\Support\Status::load( TRUE, 'status_default_staff' )->id,
'assign_to' => $this->request->staff_lock ? ( $this->request->staff ? $this->request->staff->member_id : 0 ) : 0
) );
}
}
/* Purchase tree */
else
{
\IPS\Output::i()->output = \IPS\nexus\Purchase::tree( $this->request->acpUrl(), array(), 's.' . $this->request->id, $this->request->purchase );
}
return;
}
/* Setting Order? */
if ( isset( \IPS\Request::i()->order ) )
{
\IPS\Request::i()->setCookie( 'support_order', \IPS\Request::i()->order, \IPS\DateTime::create()->add( new \DateInterval('P1Y') ) );
}
/* Views */
$this->request->setStaffView( \IPS\Member::loggedIn() );
/* Are we tracking? */
try
{
$trackLang = \IPS\Db::i()->select( 'notify', 'nexus_support_tracker', array( 'member_id=? AND request_id=?', \IPS\Member::loggedIn()->member_id, $this->request->id ) )->first() ? 'tracking_notify' : 'tracking_no_notify';
}
catch ( \UnderflowException $e )
{
$trackLang = 'not_tracking';
}
/* Init buttons */
\IPS\Output::i()->sidebar['actions'] = array(
'status' => array(
'icon' => 'tag',
'title' => $this->request->status->_title,
'menu' => array(),
'menuClass' => 'ipsMenu_selectable ipsMenu_narrow',
'data' => array( 'controller' => 'nexus.admin.support.metamenu' )
),
'severity' => array(
'icon' => 'exclamation',
'title' => $this->request->severity->_title,
'menu' => array(),
'menuClass' => 'ipsMenu_selectable',
'data' => array( 'controller' => 'nexus.admin.support.metamenu' )
),
'department' => array(
'icon' => 'folder',
'title' => $this->request->department->_title,
'menu' => array(),
'menuClass' => 'ipsMenu_selectable ipsMenu_narrow',
'data' => array( 'controller' => 'nexus.admin.support.metamenu' )
),
'staff' => array(
'icon' => 'user',
'title' => $this->request->staff ? $this->request->staff->name : 'unassigned',
'menu' => array(),
'menuClass' => 'ipsMenu_selectable',
'data' => array( 'controller' => 'nexus.admin.support.metamenu', 'role' => 'staffMenu' ),
),
'track' => array(
'icon' => 'star',
'title' => $trackLang,
'menu' => array(
array(
'class' => $trackLang === 'not_tracking' ? 'ipsMenu_itemChecked' : '',
'title' => 'not_tracking',
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'track', 'track' => 0 ) )
),
array(
'class' => $trackLang === 'tracking_no_notify' ? 'ipsMenu_itemChecked' : '',
'title' => 'tracking_no_notify',
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'track', 'track' => 1, 'notify' => 0 ) )
),
array(
'class' => $trackLang === 'tracking_notify' ? 'ipsMenu_itemChecked' : '',
'title' => 'tracking_notify',
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'track', 'track' => 1, 'notify' => 1 ) )
)
),
'menuClass' => 'ipsMenu_selectable',
'data' => array( 'controller' => 'nexus.admin.support.metamenu' )
)
);
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'requests_delete' ) )
{
\IPS\Output::i()->sidebar['actions']['delete'] = array(
'icon' => 'times-circle',
'title' => 'delete',
'link' => $this->request->acpUrl()->setQueryString( 'do', 'delete' ),
'data' => array( 'confirm' => '' )
);
}
/* Populate statuses */
foreach ( Support\Status::roots() as $status )
{
\IPS\Output::i()->sidebar['actions']['status']['menu'][] = array(
'class' => $status->id === $this->request->status->id ? 'ipsMenu_itemChecked' : '',
'title' => $status->_title,
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'status', 'status' => $status->id ) )
);
}
/* Populate severities */
if ( count( Support\Severity::roots() ) < 2 )
{
unset( \IPS\Output::i()->sidebar['actions']['severity'] );
}
else
{
foreach ( Support\Severity::roots() as $severity )
{
\IPS\Output::i()->sidebar['actions']['severity']['menu'][] = array(
'class' => $severity->id === $this->request->severity->id ? 'ipsMenu_itemChecked' : '',
'title' => $severity->_title,
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'severity', 'severity' => $severity->id ) ),
'data' => array( 'group' => 'severities' ),
);
}
if ( $this->request->member and \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'requests_block_sev' ) )
{
\IPS\Output::i()->sidebar['actions']['severity']['menu'][] = array( 'hr' => TRUE );
\IPS\Output::i()->sidebar['actions']['severity']['menu'][] = array(
'class' => !$this->request->author()->cm_no_sev ? 'ipsMenu_itemChecked' : '',
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'cm_no_sev_off', FALSE, array( 'sprintf' => array( $this->request->supportAuthor()->name() ) ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'noSev', 'no_sev' => 0 ) ),
'data' => array( 'group' => 'no_sev', 'noSet' => 'true' ),
);
\IPS\Output::i()->sidebar['actions']['severity']['menu'][] = array(
'class' => $this->request->author()->cm_no_sev ? 'ipsMenu_itemChecked' : '',
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'cm_no_sev_on', FALSE, array( 'sprintf' => array( $this->request->supportAuthor()->name() ) ) ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'noSev', 'no_sev' => 1 ) ),
'data' => array( 'group' => 'no_sev', 'noSet' => 'true' ),
);
}
}
/* Populate departments */
foreach ( Support\Department::roots() as $department )
{
\IPS\Output::i()->sidebar['actions']['department']['menu'][] = array(
'class' => $department->id === $this->request->department->id ? 'ipsMenu_itemChecked' : '',
'title' => $department->_title,
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'department', 'department' => $department->id ) )
);
}
/* Populate staff */
foreach ( Support\Request::staff() as $id => $name )
{
\IPS\Output::i()->sidebar['actions']['staff']['menu'][] = array(
'class' => ( $this->request->staff and $id === $this->request->staff->member_id ) ? 'ipsMenu_itemChecked' : '',
'title' => $name,
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staff', 'staff' => $id ) ),
'data' => array( 'group' => 'staff', 'id' => $id ),
);
}
\IPS\Output::i()->sidebar['actions']['staff']['menu'][] = array(
'class' => !$this->request->staff ? 'ipsMenu_itemChecked' : '',
'title' => 'unassigned',
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staff', 'staff' => 0 ) ),
'data' => array( 'group' => 'staff', 'id' => 0 ),
);
\IPS\Output::i()->sidebar['actions']['staff']['menu'][] = array( 'hr' => TRUE );
\IPS\Output::i()->sidebar['actions']['staff']['menu'][] = array(
'class' => $this->request->staff_lock ? 'ipsMenu_itemChecked' : '',
'title' => \IPS\Member::loggedIn()->language()->addToStack( 'request_staff_lock_on' ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staffLock', 'lock' => 1 ) ),
'data' => array( 'group' => 'staff_lock', 'noSet' => 'true' ),
);
\IPS\Output::i()->sidebar['actions']['staff']['menu'][] = array(
'class' => !$this->request->staff_lock ? 'ipsMenu_itemChecked' : '',
'title' =>\IPS\Member::loggedIn()->language()->addToStack( 'request_staff_lock_off' ),
'link' => $this->request->acpUrl()->setQueryString( array( 'do' => 'staffLock', 'lock' => 0 ) ),
'data' => array( 'group' => 'staff_lock', 'noSet' => 'true' ),
);
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack( 'request_x', FALSE, array( 'sprintf' => "#{$this->request->id}" ) );
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'admin_support.js', 'nexus', 'admin' ) );
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'support.css', 'nexus', 'admin' ) );
if ( \IPS\Theme::i()->settings['responsive'] )
{
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'support_responsive.css', 'nexus', 'admin' ) );
}
}
/**
* Pending Response Send/Discard
*
* @return void
*/
protected function pending()
{
try
{
$message = Support\Reply::loadAndCheckPerms( \IPS\Request::i()->response );
if ( \IPS\Request::i()->send )
{
$message->sendPending();
}
else
{
$message->delete();
}
\IPS\Output::i()->redirect( $message->item()->acpUrl()->setQueryString( array( 'filter' => \IPS\Request::i()->filter, 'sort' => \IPS\Request::i()->sort ) ) );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/1', 404, '' );
}
}
/**
* Edit Title
*
* @return void
*/
protected function editTitle()
{
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Text( 'support_title', $request->title, TRUE, array( 'maxLength' => 255 ) ) );
if ( $values = $form->values() )
{
$request->title = $values['support_title'];
$request->save();
\IPS\Output::i()->redirect( $request->acpUrl() );
}
\IPS\Output::i()->output = $form;
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/2', 404, '' );
}
}
/**
* Edit Custom Fields
*
* @return void
*/
protected function cfields()
{
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$customFieldValues = $request->cfields;
$form = new \IPS\Helpers\Form;
foreach ( $request->department->customFields() as $field )
{
$form->add( $field->buildHelper( isset( $customFieldValues[ $field->id ] ) ? $customFieldValues[ $field->id ] : NULL ) );
}
if ( $values = $form->values( TRUE ) )
{
$save = array();
foreach ( $values as $k => $v )
{
$save[ mb_substr( $k, 13 ) ] = $v;
}
$request->cfields = $save;
$request->save();
\IPS\Output::i()->redirect( $request->acpUrl() );
}
\IPS\Output::i()->output = $form;
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/3', 404, '' );
}
}
/**
* Set Status
*
* @return void
*/
protected function status()
{
try
{
/* Init */
$return = array();
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$status = Support\Status::load( \IPS\Request::i()->status );
$oldStatus = $request->status;
$request->status = $status;
/* Assign it if we have to */
if ( $status->assign )
{
if ( $request->staff and $request->staff->member_id != \IPS\Member::loggedIn()->member_id )
{
$return['alert'] = \IPS\Member::loggedIn()->language()->addToStack( 'you_have_stolen_request', FALSE, array( 'sprintf' => array( $request->staff->name ) ) );
}
$request->staff = \IPS\Member::loggedIn();
$return['staff'] = array( 'id' => \IPS\Member::loggedIn()->member_id, 'name' => \IPS\Member::loggedIn()->name );
}
/* Or set the previous status was "Working", release our assigning */
elseif ( $oldStatus->assign and $request->staff )
{
$request->staff = NULL;
$return['staff'] = array( 'id' => 0, 'name' => \IPS\Member::loggedIn()->language()->addToStack('unassigned') );
}
$request->save();
/* Log */
if ( $status->log )
{
$request->log( 'status', $oldStatus, $status );
}
/* Return */
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( $return );
}
else
{
\IPS\Output::i()->redirect( $request->acpUrl() );
}
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/4', 404, '' );
}
}
/**
* Set Severity
*
* @return void
*/
protected function severity()
{
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$new = Support\Severity::load( \IPS\Request::i()->severity );
$request->log( 'severity', $request->severity, $new );
$request->severity = $new;
$request->save();
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( array() );
}
\IPS\Output::i()->redirect( $request->acpUrl() );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/5', 404, '' );
}
}
/**
* Control member's permission to set severities
*
* @return void
*/
protected function noSev()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'requests_block_sev' );
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$request->author()->cm_no_sev = \IPS\Request::i()->no_sev;
$request->author()->save();
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( array() );
}
\IPS\Output::i()->redirect( $request->acpUrl() );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/6', 404, '' );
}
}
/**
* Staff Lock
*
* @return void
*/
protected function staffLock()
{
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$request->staff_lock = \IPS\Request::i()->lock;
$request->save();
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( array( 'assign_to' => ( $request->staff_lock ? ( $request->staff ? $request->staff->member_id : 0 ) : 0 ) ) );
}
\IPS\Output::i()->redirect( $request->acpUrl() );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/7', 404, '' );
}
}
/**
* Set Department
*
* @return void
*/
protected function department()
{
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$new = Support\Department::load( \IPS\Request::i()->department );
$request->log( 'department', $request->department, $new );
$request->department = $new;
$request->save();
if ( \IPS\Request::i()->isAjax() )
{
$stockActionOptions = array();
$stockActions = array( 0 => '' );
foreach ( \IPS\nexus\Support\StockAction::roots( NULL, NULL, "action_show_in='*' OR " . \IPS\Db::i()->findInSet( 'action_show_in', array( $request->department->id ) ) ) as $action )
{
$stockActions[ $action->id ] = $action->_title;
}
\IPS\Output::i()->json( array( 'department' => \IPS\Request::i()->department, 'stockActions' => $stockActions, 'requiresPurchase' => (bool) $request->department->require_package ) );
}
\IPS\Output::i()->redirect( $request->acpUrl() );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/8', 404, '' );
}
}
/**
* Set Staff
*
* @return void
*/
protected function staff()
{
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$new = \IPS\Request::i()->staff ? \IPS\Member::load( \IPS\Request::i()->staff ) : NULL;
$request->log( 'staff', $request->staff, $new );
$request->staff = $new;
$request->save();
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( array( 'assign_to' => ( $request->staff_lock ? ( $request->staff ? $request->staff->member_id : 0 ) : 0 ) ) );
}
\IPS\Output::i()->redirect( $request->acpUrl() );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/9', 404, '' );
}
}
/**
* Track
*
* @return void
*/
protected function track()
{
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
if ( \IPS\Request::i()->track )
{
\IPS\Db::i()->insert( 'nexus_support_tracker', array(
'member_id' => \IPS\Member::loggedIn()->member_id,
'request_id' => $request->id,
'notify' => \IPS\Request::i()->notify
), TRUE );
}
else
{
\IPS\Db::i()->delete( 'nexus_support_tracker', array( 'member_id=? AND request_id=?', \IPS\Member::loggedIn()->member_id, $request->id ) );
}
if ( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( array() );
}
\IPS\Output::i()->redirect( $request->acpUrl() );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/A', 404, '' );
}
}
/**
* Associate
*
* @return void
*/
protected function associate()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'purchases_view', 'nexus', 'customers' );
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$form = new \IPS\Helpers\Form;
$form->class = 'ipsForm_vertical ipsForm_noLabels';
$form->add( new \IPS\Helpers\Form\Node( 'associated_purchase', $request->purchase, TRUE, array( 'class' => 'IPS\nexus\Purchase', 'forceOwner' => $request->author(), 'zeroVal' => 'none' ) ) );
if ( $values = $form->values() )
{
$request->log( 'purchase', $request->purchase, $values['associated_purchase'] ?: NULL );
$request->purchase = $values['associated_purchase'] ?: NULL;
$request->save();
\IPS\Output::i()->redirect( $request->acpUrl() );
}
\IPS\Output::i()->output = $form->customTemplate( array( call_user_func_array( array( \IPS\Theme::i(), 'getTemplate' ), array( 'forms', 'core', 'front' ) ), 'popupTemplate' ) );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/B', 404, '' );
}
}
/**
* Merge
*
* @return void
*/
protected function merge()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'requests_merge' );
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$request->mergeIn( array( Support\Request::loadAndCheckPerms( \IPS\Request::i()->merge ) ) ) ;
\IPS\Output::i()->redirect( $request->acpUrl() );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/C', 404, '' );
}
}
/**
* Delete
*
* @return void
*/
protected function delete()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'requests_delete' );
try
{
$request = Support\Request::loadAndCheckPerms( \IPS\Request::i()->id );
$request->delete();
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( "app=nexus&module=support&controller=requests" ) );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/D', 404, '' );
}
}
/**
* Delete Reply
*
* @return void
*/
protected function deleteReply()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'requests_reply_delete' );
try
{
$reply = Support\Reply::loadAndCheckPerms( \IPS\Request::i()->id );
$reply->delete();
\IPS\Output::i()->redirect( $reply->item()->acpUrl() );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/G', 404, '' );
}
}
/**
* View Feedback
*
* @return void
*/
protected function feedback()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'requests_ratings_feedback' );
try
{
$reply = \IPS\nexus\Support\Reply::loadAndCheckPerms( \IPS\Request::i()->id );
}
catch ( \OutOfRangeException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/E', 404, '' );
}
$rating = NULL;
try
{
$rating = \IPS\Db::i()->select( '*', 'nexus_support_ratings', array( 'rating_reply=?', $reply->id ) )->first();
}
catch ( \UnderflowException $e )
{
\IPS\Output::i()->error( 'node_error', '2X208/F', 404, '' );
}
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'support' )->feedback( $rating );
}
}
@@ -0,0 +1,588 @@
<?php
/**
* @brief Support Requests
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 09 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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 Requests
*/
class _requests extends \IPS\Dispatcher\Controller
{
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'support.css', 'nexus', 'admin' ) );
if ( \IPS\Theme::i()->settings['responsive'] )
{
\IPS\Output::i()->cssFiles = array_merge( \IPS\Output::i()->cssFiles, \IPS\Theme::i()->css( 'support_responsive.css', 'nexus', 'admin' ) );
}
\IPS\Dispatcher::i()->checkAcpPermission( 'requests_manage' );
parent::execute();
}
/**
* Manage
*
* @return void
*/
protected function manage()
{
/* Can we access anything? */
if ( !count( \IPS\nexus\Support\Department::departmentsWithPermission() ) )
{
if ( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'departments_manage' ) )
{
\IPS\Output::i()->error( 'err_no_departments_with_perm1', '1X261/1', 403, '' );
}
else
{
\IPS\Output::i()->error( 'err_no_departments_with_perm2', '1X261/2', 403, '' );
}
}
/* URL */
$url = \IPS\Http\Url::internal( 'app=nexus&module=support&controller=requests' );
$customer = NULL;
$where = array();
if ( isset( \IPS\Request::i()->member ) )
{
try
{
$customer = \IPS\nexus\Customer::load( \IPS\Request::i()->member );
$url = $url->setQueryString( 'member', $customer->member_id );
$where[] = array( 'r_member=?', $customer->member_id );
}
catch ( \OutOfRangeException $e ) { }
}
/* Permissions */
$where[] = array( "( dpt_staff='*' OR " . \IPS\Db::i()->findInSet( 'dpt_staff', \IPS\nexus\Support\Department::staffDepartmentPerms() ) . ')' );
/* Filters */
if ( isset( \IPS\Request::i()->assigned ) )
{
$where[] = array( 'r_staff=?', \IPS\Member::loggedIn()->member_id );
}
if ( isset( \IPS\Request::i()->tracked ) )
{
$where[] = array( 'request_id IS NOT NULL' );
}
if ( isset( \IPS\Request::i()->replied ) )
{
$where[] = array( 'r_id IN(?)', \IPS\Db::i()->select( 'DISTINCT(reply_request)', 'nexus_support_replies', array( 'reply_member=?', \IPS\Member::loggedIn()->member_id ) ) );
}
/* Departments / Statuses */
$myFilters = \IPS\nexus\Support\Request::myFilters();
if ( isset( \IPS\Request::i()->departments ) or isset( \IPS\Request::i()->statuses ) )
{
$newFilters = array( 'departments' => isset( \IPS\Request::i()->departments ) ? explode( ',', \IPS\Request::i()->departments ) : $myFilters['departments'], 'statuses' => isset( \IPS\Request::i()->statuses ) ? explode( ',', \IPS\Request::i()->statuses ) : $myFilters['statuses'] );
\IPS\Request::i()->setCookie( 'support_filters', json_encode( $newFilters ), \IPS\DateTime::create()->add( new \DateInterval( 'P1Y' ) ) );
$myFilters = \IPS\nexus\Support\Request::myFilters( $newFilters );
}
$where[] = $myFilters['whereClause'];
/* Create the table */
$table = \IPS\nexus\Support\Request::table( $url, $where );
$table->classes[] = 'cNexusSupportTable';
$table->tableTemplate = array( \IPS\Theme::i()->getTemplate( 'support', 'nexus', 'admin' ), 'requestTable' );
$table->rowsTemplate = array( \IPS\Theme::i()->getTemplate( 'support', 'nexus', 'admin' ), 'requestRows' );
/* Search */
$table->quickSearch = 'r_title';
$table->advancedSearch = array(
'r_title_or_message'=> array( \IPS\Helpers\Table\SEARCH_CUSTOM, array(
'getHtml' => function( $field )
{
return \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->text( $field->name, 'text', $field->value, $field->required );
}
), function( $v )
{
return array( 'r_title LIKE ? OR ' . \IPS\Db::i()->in( 'r_id', \IPS\Db::i()->select( 'reply_request', 'nexus_support_replies', array( "MATCH(reply_post) AGAINST (? IN BOOLEAN MODE)", $v ) ) ), '%' . $v . '%' );
} ),
'r_severity' => array( \IPS\Helpers\Table\SEARCH_NODE, array( 'class' => 'IPS\nexus\Support\Severity', 'multiple' => TRUE ) ),
'r_department' => array( \IPS\Helpers\Table\SEARCH_NODE, array( 'class' => 'IPS\nexus\Support\Department', 'multiple' => TRUE ) ),
'r_member' => \IPS\Helpers\Table\SEARCH_MEMBER,
'r_email' => \IPS\Helpers\Table\SEARCH_CONTAINS_TEXT,
'r_replies' => \IPS\Helpers\Table\SEARCH_NUMERIC,
'r_started' => \IPS\Helpers\Table\SEARCH_DATE_RANGE,
'r_last_new_reply' => \IPS\Helpers\Table\SEARCH_DATE_RANGE,
'r_last_reply' => \IPS\Helpers\Table\SEARCH_DATE_RANGE,
'r_last_reply_by' => \IPS\Helpers\Table\SEARCH_MEMBER,
'r_last_staff_reply'=> \IPS\Helpers\Table\SEARCH_DATE_RANGE,
'r_status' => array( \IPS\Helpers\Table\SEARCH_NODE, array( 'class' => 'IPS\nexus\Support\Status', 'multiple' => TRUE ) ),
'r_staff' => array( \IPS\Helpers\Table\SEARCH_SELECT, array( 'options' => \IPS\nexus\Support\Request::staff(), 'multiple' => TRUE, 'noDefault' => TRUE ) ),
);
/* Display */
\IPS\Output::i()->title = $customer ? \IPS\Member::loggedIn()->language()->addToStack( 'members_support_requests', FALSE, array( 'sprintf' => array( $customer->cm_name ) ) ) : \IPS\Member::loggedIn()->language()->addToStack('menu__nexus_support_requests');
\IPS\Output::i()->output .= \IPS\Theme::i()->getTemplate( 'global', 'core' )->block( 'title', (string) $table );
/* Create Button */
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'requests_create' ) )
{
$createUrl = \IPS\Http\Url::internal('app=nexus&module=support&controller=requests&do=create&_new=1');
if ( $customer )
{
$createUrl = $createUrl->setQueryString( 'member', $customer->member_id );
}
\IPS\Output::i()->sidebar['actions']['create'] = array(
'icon' => 'plus',
'title' => 'add',
'link' => $createUrl,
);
}
/* Settings */
\IPS\Output::i()->sidebar['actions']['notifications'] = array(
'icon' => 'envelope',
'title' => 'my_notifications',
'link' => \IPS\Http\Url::internal('app=nexus&module=support&controller=requests&do=notifications'),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('my_notifications') )
);
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'support_display_settings' ) )
{
\IPS\Output::i()->sidebar['actions']['settings'] = array(
'icon' => 'cog',
'title' => 'display_settings',
'link' => \IPS\Http\Url::internal('app=nexus&module=support&controller=requests&do=settings'),
'data' => array( 'ipsDialog' => '', 'ipsDialog-title' => \IPS\Member::loggedIn()->language()->addToStack('display_settings') )
);
}
}
/**
* Reset my departments
*
* @return void
*/
protected function resetMyDepartments()
{
\IPS\Request::i()->setCookie( 'support_filters', '', \IPS\DateTime::create()->sub( new \DateInterval( 'P1D' ) ) );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=requests') );
}
/**
* My Notifications
*
* @return void
*/
protected function notifications()
{
$types = array( 'support_notify_new' => 'n', 'support_notify_replies' => 'r', 'support_notify_assign' => 'a' );
$existing = iterator_to_array( \IPS\Db::i()->select( '*', 'nexus_support_notify', array( 'staff_id=?', \IPS\Member::loggedIn()->member_id ) )->setKeyField('type')->setValueField('departments') );
$myDepartments = array();
foreach ( \IPS\nexus\Support\Department::roots( NULL, NULL, array( "dpt_staff='*' OR " . \IPS\Db::i()->findInSet( 'dpt_staff', \IPS\nexus\Support\Department::staffDepartmentPerms() ) ) ) as $dpt )
{
$myDepartments[ $dpt->id ] = $dpt->_title;
}
$form = new \IPS\Helpers\Form;
$form->addMessage( 'support_notify_blurb' );
$form->addHeader('notify_me_when');
foreach ( $types as $k => $t )
{
$form->add( new \IPS\Helpers\Form\Select( $k, isset( $existing[ $t ] ) ? ( $existing[ $t ] === '*' ? 0 : explode( ',', $existing[ $t ] ) ) : NULL, FALSE, array( 'options' => $myDepartments, 'multiple' => TRUE, 'unlimited' => 0, 'unlimitedLang' => 'all' ) ) );
}
if ( $values = $form->values() )
{
\IPS\Db::i()->delete( 'nexus_support_notify', array( 'staff_id=?', \IPS\Member::loggedIn()->member_id ) );
foreach ( $types as $k => $t )
{
if ( $values[ $k ] === 0 or count( $values[ $k ] ) )
{
\IPS\Db::i()->insert( 'nexus_support_notify', array(
'staff_id' => \IPS\Member::loggedIn()->member_id,
'type' => $t,
'departments' => ( $values[ $k ] === 0 ) ? '*' : implode( ',', $values[ $k ] )
) );
}
}
\IPS\Output::i()->redirect( \IPS\Http\Url::internal("app=nexus&module=support&controller=requests") );
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('my_notifications');
\IPS\Output::i()->output = $form;
}
/**
* Display Settings
*
* @return void
*/
protected function settings()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'support_display_settings' );
$form = new \IPS\Helpers\Form;
$form->add( new \IPS\Helpers\Form\Custom( 'support_old_highlight', array( \IPS\Settings::i()->support_old_stat, \IPS\Settings::i()->support_old_number ), FALSE, array(
'getHtml' => function( $obj )
{
$number = \IPS\Settings::i()->support_old_number;
$numberType = $number ? 'minutes' : 'hours';
if ( $number % 1440 === 0 )
{
$number /= 1440; # Fun fact: that's the first time I've used that operator
$numberType = 'days';
}
elseif ( $number % 60 === 0 )
{
$number /= 60; # Fun fact: that's the second time I've used that operator
$numberType = 'hours';
}
return \IPS\Theme::i()->getTemplate('support')->highlightSetting( $obj->name, $obj->value[0], $number, $numberType );
}
) ) );
if ( $values = $form->values() )
{
$save = array();
if ( isset( $values['support_old_highlight'][3] ) )
{
$save['support_old_number'] = 0;
}
else
{
$save['support_old_stat'] = $values['support_old_highlight'][0];
switch ( $values['support_old_highlight'][2] )
{
case 'minutes':
$save['support_old_number'] = $values['support_old_highlight'][1];
break;
case 'hours':
$save['support_old_number'] = $values['support_old_highlight'][1] * 60;
break;
case 'days':
$save['support_old_number'] = $values['support_old_highlight'][1] * 1440;
break;
}
}
$form->saveAsSettings( $save );
\IPS\Session::i()->log( 'acplogs__support_display_settings' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=requests' ), 'saved' );
}
\IPS\Output::i()->output = $form;
}
/**
* Create
*
* @return void
*/
protected function create()
{
/* Init */
\IPS\Dispatcher::i()->checkAcpPermission( 'requests_create' );
$steps = array();
/* Owner */
$steps['request_owner'] = function( $data )
{
$form = new \IPS\Helpers\Form( 'owner', 'continue' );
$form->add( new \IPS\Helpers\Form\Radio( 'request_owner_type', 'member', TRUE, array(
'options' => array( 'member' => 'request_owner_member', 'email' => 'request_owner_email' ),
'toggles' => array( 'member' => array( 'request_owner_member' ), 'email' => array( 'request_owner_email' ) )
) ) );
$form->add( new \IPS\Helpers\Form\Member( 'request_owner_member', isset( \IPS\Request::i()->member ) ? \IPS\Member::load( \IPS\Request::i()->member ) : NULL, FALSE, array(), NULL, NULL, NULL, 'request_owner_member' ) );
$form->add( new \IPS\Helpers\Form\Email( 'request_owner_email', NULL, FALSE, array(), NULL, NULL, NULL, 'request_owner_email' ) );
if ( $values = $form->values() )
{
if ( $values['request_owner_type'] === 'member' )
{
if ( !$values['request_owner_member'] )
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack('request_owner_req');
return (string) $form;
}
$data['member'] = $values['request_owner_member']->member_id;
}
else
{
if ( !$values['request_owner_email'] )
{
$form->error = \IPS\Member::loggedIn()->language()->addToStack('request_owner_req');
return (string) $form;
}
$member = \IPS\Member::load( $values['request_owner_email'], 'email' );
if ( $member->member_id )
{
$data['member'] = $member->member_id;
}
else
{
$data['email'] = $values['request_owner_email'];
}
}
return $data;
}
return (string) $form;
};
/* Stock Actions */
$stockActions = \IPS\nexus\Support\StockAction::roots();
if ( count( $stockActions ) )
{
$steps['stock_action'] = function( $data ) use ( $stockActions )
{
$options = array( 0 => 'none' );
foreach ( $stockActions as $action )
{
$options[ $action->id ] = $action->_title;
}
$form = new \IPS\Helpers\Form( 'stock_action', 'continue' );
$form->add( new \IPS\Helpers\Form\Radio( 'stock_action', 0, FALSE, array(
'options' => $options
) ) );
if ( $values = $form->values() )
{
$data['stock_action'] = $values['stock_action'];
return $data;
}
return (string) $form;
};
}
/* Request Details */
$steps['request_details'] = function( $data ) use ( $stockActions )
{
$stockAction = NULL;
if ( isset( $data['stock_action'] ) and isset( $stockActions[ $data['stock_action'] ] ) )
{
$stockAction = $stockActions[ $data['stock_action'] ];
}
$form = new \IPS\Helpers\Form( 'request_details', 'continue' );
$form->add( new \IPS\Helpers\Form\Text( 'support_title', NULL, TRUE ) );
$form->add( new \IPS\Helpers\Form\Node( 'support_department', $stockAction ? $stockAction->department : NULL, TRUE, array( 'class' => 'IPS\nexus\Support\Department' ) ) );
if ( isset( $data['member'] ) )
{
$form->add( new \IPS\Helpers\Form\Node( 'support_purchase', 0, FALSE, array( 'class' => 'IPS\nexus\Purchase', 'forceOwner' => \IPS\Member::load( $data['member'] ), 'zeroVal' => 'none' ) ) );
}
$form->add( new \IPS\Helpers\Form\Node( 'r_status', $stockAction ? $stockAction->status : \IPS\nexus\Support\Status::load( TRUE, 'status_default_staff' ), TRUE, array( 'class' => 'IPS\nexus\Support\Status' ) ) );
$form->add( new \IPS\Helpers\Form\Node( 'support_severity', \IPS\nexus\Support\Severity::load( TRUE, 'sev_default' ), TRUE, array( 'class' => 'IPS\nexus\Support\Severity' ) ) );
$form->add( new \IPS\Helpers\Form\Select( 'r_staff', 0, FALSE, array( 'options' => array_merge( array( 0 => '' ), \IPS\nexus\Support\Request::staff() ) ) ) );
if ( $values = $form->values() )
{
$data['title'] = $values['support_title'];
$data['department'] = $values['support_department']->id;
if ( isset( $values['support_purchase'] ) and $values['support_purchase'] )
{
$data['purchase'] = $values['support_purchase']->id;
}
$data['status'] = $values['r_status']->id;
$data['severity'] = $values['support_severity']->id;
$data['staff'] = $values['r_staff'];
return $data;
}
return (string) $form;
};
/* Custom Fields */
$customFields = \IPS\nexus\Support\CustomField::roots();
if ( count( $customFields ) )
{
$steps['custom_support_fields'] = function( $data )
{
$customFields = \IPS\nexus\Support\CustomField::roots( NULL, NULL, array( "sf_departments='*' OR " . \IPS\Db::i()->findInSet( 'sf_departments', array( $data['department'] ) ) ) );
if ( count( $customFields ) )
{
$form = new \IPS\Helpers\Form( 'custom_fields', 'continue' );
foreach ( $customFields as $field )
{
$form->add( $field->buildHelper() );
}
if ( $values = $form->values() )
{
$data['custom_fields'] = $values;
return $data;
}
return (string) $form;
}
else
{
return $data;
}
};
}
/* Your Message */
$steps['your_message'] = function( $data ) use ( $stockActions )
{
$stockAction = NULL;
if ( isset( $data['stock_action'] ) and isset( $stockActions[ $data['stock_action'] ] ) )
{
$stockAction = $stockActions[ $data['stock_action'] ];
}
$form = new \IPS\Helpers\Form( 'your_message' );
$form->add( new \IPS\Helpers\Form\Email( 'to', isset( $data['member'] ) ? \IPS\Member::load( $data['member'] )->email : $data['email'] ) );
$form->add( new \IPS\Helpers\Form\Text( 'cc', array(), FALSE, array( 'autocomplete' => array( 'unique' => TRUE, 'forceLower' => TRUE ) ), array( 'IPS\nexus\Support\Request', '_validateEmail' ) ) );
$form->add( new \IPS\Helpers\Form\Text( 'bcc', array(), FALSE, array( 'autocomplete' => array( 'unique' => TRUE, 'forceLower' => TRUE ) ), array( 'IPS\nexus\Support\Request', '_validateEmail' ) ) );
$form->add( new \IPS\Helpers\Form\Editor( 'message', $stockAction ? $stockAction->message : NULL, TRUE, array( 'app' => 'nexus', 'key' => 'Support', 'autoSaveKey' => md5( "new-req-message" ) ) ) );
if ( $values = $form->values() )
{
$request = new \IPS\nexus\Support\Request;
$request->started = time();
$request->title = $data['title'];
if ( isset( $data['member'] ) )
{
$request->member = $data['member'];
}
else
{
$request->email = $data['email'];
}
$request->department = \IPS\nexus\Support\Department::load( $data['department'] );
if ( isset( $data['purchase'] ) and $data['purchase'] )
{
$request->purchase = \IPS\nexus\Purchase::load( $data['purchase'] );
}
$request->status = \IPS\nexus\Support\Status::load( $data['status'] );
$request->severity = \IPS\nexus\Support\Severity::load( $data['severity'] );
if ( isset( $data['staff'] ) and $data['staff'] )
{
$request->staff = \IPS\Member::load( $data['staff'] );
}
if ( isset( $data['custom_fields'] ) )
{
$cfields = array();
foreach ( $data['custom_fields'] as $k => $v )
{
$cfields[ mb_substr( $k, 13 ) ] = $v;
}
$request->cfields = $cfields;
}
$notify = $request->notify;
foreach ( $values['cc'] as $cc )
{
foreach ( $notify as $n )
{
if ( $n['value'] === $cc )
{
continue 2;
}
}
$notify[] = array( 'type' => 'e', 'value' => $cc );
}
foreach ( $values['bcc'] as $cc )
{
foreach ( $notify as $k => $n )
{
if ( $n['value'] === $cc )
{
if ( $n['bcc'] )
{
unset( $notify[ $k ]['bcc'] );
}
continue 2;
}
}
$notify[] = array( 'type' => 'e', 'value' => $cc, 'bcc' => 1 );
}
$request->notify = $notify;
$request->last_reply = time();
$request->last_new_reply = time();
$request->last_staff_reply = time();
$request->last_reply_by = \IPS\Member::loggedIn()->member_id;
$request->replies = 1;
$request->save();
$reply = new \IPS\nexus\Support\Reply;
$reply->request = $request->id;
$reply->member = \IPS\Member::loggedIn()->member_id;
$reply->type = $reply::REPLY_STAFF;
$reply->post = $values['message'];
$reply->date = time();
$reply->cc = implode( ',', $values['cc'] );
$reply->ip_address = \IPS\Request::i()->ipAddress();
$reply->bcc = implode( ',', $values['bcc'] );
$reply->save();
$request->processAfterCreate( $reply, $data );
$reply->sendCustomerNotifications( $values['to'], $values['cc'], $values['bcc'] );
$reply->sendNotifications();
$url = NULL;
if ( isset( $data['ref'] ) and isset( $data['transaction'] ) )
{
try
{
$transaction = \IPS\nexus\Transaction::load( $data['transaction'] );
$extra = $transaction->extra;
$extra['sr'] = $transaction->id;
$transaction->extra = $extra;
$transaction->save();
switch ( $data['ref'] )
{
case 'v':
\IPS\Output::i()->redirect( $transaction->acpUrl() );
break;
case 'i':
\IPS\Output::i()->redirect( $transaction->invoice->acpUrl() );
break;
case 'c':
\IPS\Output::i()->redirect( $transaction->member->acpUrl() );
break;
case 't':
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=payments&controller=transactions') );
break;
}
}
catch ( \OutOfRangeException $e ) { }
}
if ( !$url )
{
$url = $request->canView() ? $request->acpUrl() : \IPS\Http\Url::internal('app=nexus&module=support&controller=requests');
}
\IPS\Output::i()->redirect( $url, 'request_created' );
}
return $form;
};
/* Display */
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('create_support_request');
\IPS\Output::i()->output = new \IPS\Helpers\Wizard( $steps, \IPS\Http\Url::internal('app=nexus&module=support&controller=requests&do=create') );
}
}
@@ -0,0 +1,100 @@
<?php
/**
* @brief Support Settings
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 15 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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;
}
/**
* Payment Settings
*/
class _settings extends \IPS\Dispatcher\Controller
{
/**
* Call
*
* @return void
*/
public function __call( $method, $args )
{
$tabs = array();
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'departments_manage' ) )
{
$tabs['departments'] = 'departments';
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'stockactions_manage' ) )
{
$tabs['stockactions'] = 'stock_actions';
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'scfields_manage' ) )
{
$tabs['fields'] = 'custom_support_fields';
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'severities_manage' ) )
{
$tabs['severities'] = 'severities';
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'statuses_manage' ) )
{
$tabs['statuses'] = 'statuses';
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'autoresolve_manage' ) )
{
$tabs['autoresolve'] = 'autoresolve';
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'customerfeedback_manage' ) )
{
$tabs['customerfeedback'] = 'customer_feedback';
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'outgoingemail_manage' ) )
{
$tabs['outgoingemail'] = 'outgoing_emails';
}
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'support', 'incomingemail_manage' ) )
{
$tabs['incomingemail'] = 'incoming_emails';
}
if ( isset( \IPS\Request::i()->tab ) and isset( $tabs[ \IPS\Request::i()->tab ] ) )
{
$activeTab = \IPS\Request::i()->tab;
}
else
{
$_tabs = array_keys( $tabs ) ;
$activeTab = array_shift( $_tabs );
}
$classname = 'IPS\nexus\modules\admin\support\\' . $activeTab;
$class = new $classname;
$class->url = \IPS\Http\Url::internal("app=nexus&module=support&controller=settings&tab={$activeTab}");
$class->execute();
if ( $method === 'manage' and \IPS\Member::loggedIn()->language()->checkKeyExists( $tabs[ $activeTab ] . '_blurb' ) )
{
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->blurb( $tabs[ $activeTab ] . '_blurb', TRUE, TRUE ) . \IPS\Output::i()->output;
}
if ( $method !== 'manage' or \IPS\Request::i()->isAjax() )
{
return;
}
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('support_settings');
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate( 'global', 'core' )->tabs( $tabs, $activeTab, \IPS\Output::i()->output, \IPS\Http\Url::internal( "app=nexus&module=support&controller=settings" ) );
}
}
@@ -0,0 +1,129 @@
<?php
/**
* @brief severities
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage
* @since 09 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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;
}
/**
* severities
*/
class _severities extends \IPS\Node\Controller
{
/**
* Node Class
*/
protected $nodeClass = 'IPS\nexus\Support\Severity';
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'severities_manage' );
parent::execute();
}
/**
* Manage
*
* @return void
*/
protected function manage()
{
parent::manage();
if ( isset( \IPS\Request::i()->nexus_severities ) )
{
\IPS\Db::i()->update( 'core_sys_conf_settings', array( 'conf_value' => \IPS\Request::i()->nexus_severities ), array( 'conf_key=?', 'nexus_severities' ) );
\IPS\Settings::i()->nexus_severities = \IPS\Request::i()->nexus_severities;
unset( \IPS\Data\Store::i()->settings );
\IPS\Session::i()->log( 'acplogs__severity_settings' );
\IPS\Output::i()->redirect( \IPS\Http\Url::internal('app=nexus&module=support&controller=settings&tab=severities') );
}
\IPS\Output::i()->output = \IPS\Theme::i()->getTemplate('support')->severities( \IPS\Output::i()->output );
}
/**
* Delete
*
* @return void
*/
protected function delete()
{
try
{
$node = \IPS\nexus\Support\Severity::load( \IPS\Request::i()->id );
if ( $node->default )
{
\IPS\Output::i()->error( 'cannot_delete_default_severity', '1X211/1', 403, '' );
}
if ( $node->canDelete() )
{
if ( \IPS\Db::i()->select( 'COUNT(*)', 'nexus_support_requests', array( 'r_severity=?', $node->id ) ) )
{
$form = new \IPS\Helpers\Form( 'delete', 'delete' );
$form->add( new \IPS\Helpers\Form\Node( 'set_existing_requests_to', NULL, TRUE, array( 'class' => 'IPS\nexus\Support\Severity', 'permissionCheck' => function( $_node ) use ( $node )
{
return $node->id != $_node->id;
} ) ) );
if ( $values = $form->values() )
{
/* Update */
\IPS\Db::i()->update( 'nexus_support_requests', array( 'r_severity' => $values['set_existing_requests_to']->id ), array( 'r_severity=?', $node->id ) );
/* Delete it */
\IPS\Session::i()->log( 'acplog__node_deleted', array( $this->title => TRUE, $node->_logKey => TRUE ) );
$node->delete();
/* Clear out member's cached "Create Menu" contents */
\IPS\Member::clearCreateMenu();
/* Boink */
if( \IPS\Request::i()->isAjax() )
{
\IPS\Output::i()->json( "OK" );
}
else
{
\IPS\Output::i()->redirect( $this->url->setQueryString( array( 'root' => ( $node->parent() ? $node->parent()->_id : '' ) ) ), 'deleted' );
}
}
\IPS\Output::i()->output = $form;
return;
}
else
{
return parent::delete();
}
}
else
{
return parent::delete();
}
}
catch ( \OutOfRangeException $e )
{
return parent::delete();
}
}
}
@@ -0,0 +1,79 @@
<?php
/**
* @brief Support Statuses
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 09 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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 Departments
*/
class _statuses extends \IPS\Node\Controller
{
/**
* Node Class
*/
protected $nodeClass = 'IPS\nexus\Support\Status';
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'statuses_manage' );
parent::execute();
}
/**
* Delete
*
* @return void
*/
protected function delete()
{
try
{
$node = \IPS\nexus\Support\Status::load( \IPS\Request::i()->id );
if ( $node->default_staff or $node->default_member )
{
\IPS\Output::i()->error( 'cannot_delete_default_status', '1X210/1', 403, '' );
}
if ( $node->canDelete() and \IPS\Db::i()->select( 'COUNT(*)', 'nexus_support_requests', array( 'r_status=?', $node->id ) )->first() )
{
$form = new \IPS\Helpers\Form( 'delete', 'delete' );
$form->add( new \IPS\Helpers\Form\Node( 'set_existing_requests_to', NULL, TRUE, array( 'class' => 'IPS\nexus\Support\Status', 'permissionCheck' => function( $_node ) use ( $node )
{
return $node->id != $_node->id;
} ) ) );
if ( $values = $form->values() )
{
\IPS\Db::i()->update( 'nexus_support_requests', array( 'r_status' => $values['set_existing_requests_to']->id ), array( 'r_status=?', $node->id ) );
return parent::delete();
}
\IPS\Output::i()->output = $form;
return;
}
}
catch ( \OutOfRangeException $e ){}
return parent::delete();
}
}
@@ -0,0 +1,42 @@
<?php
/**
* @brief stockactions
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage
* @since 15 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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;
}
/**
* stockactions
*/
class _stockactions extends \IPS\Node\Controller
{
/**
* Node Class
*/
protected $nodeClass = 'IPS\nexus\Support\StockAction';
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'stockactions_manage' );
parent::execute();
}
}
@@ -0,0 +1,60 @@
<?php
/**
* @brief New Support Request Volumme
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
* @license http://www.invisionpower.com/legal/standards/
* @package IPS Social Suite
* @subpackage Nexus
* @since 25 Apr 2014
* @version SVN_VERSION_NUMBER
*/
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;
}
/**
* volume
*/
class _volume extends \IPS\Dispatcher\Controller
{
/**
* Execute
*
* @return void
*/
public function execute()
{
\IPS\Dispatcher::i()->checkAcpPermission( 'volume_manage' );
parent::execute();
}
/**
* View
*
* @return void
*/
protected function manage()
{
$chart = new \IPS\Helpers\Chart\Dynamic( \IPS\Http\Url::internal( 'app=nexus&module=support&controller=volume' ), 'nexus_support_requests', 'r_started', '',
array(
'vAxis' => array( 'title' => \IPS\Member::loggedIn()->language()->addToStack('support_requests_created') ),
),
'LineChart'
);
$chart->groupBy = 'r_department';
foreach( \IPS\nexus\Support\Department::roots() as $department )
{
$chart->addSeries( $department->_title, 'number', 'COUNT(*)', TRUE, $department->id );
}
\IPS\Output::i()->output = (string) $chart;
\IPS\Output::i()->title = \IPS\Member::loggedIn()->language()->addToStack('menu__nexus_support_volume');
}
}