469 lines
13 KiB
PHP
469 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* @brief Support Requests Stream
|
|
* @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 11 Sep 2016
|
|
*/
|
|
|
|
namespace 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 Requests Stream
|
|
*/
|
|
class _Stream extends \IPS\Patterns\ActiveRecord
|
|
{
|
|
/**
|
|
* @brief [ActiveRecord] Multiton Store
|
|
*/
|
|
protected static $multitons;
|
|
|
|
/**
|
|
* @brief [ActiveRecord] Database Table
|
|
*/
|
|
public static $databaseTable = 'nexus_support_streams';
|
|
|
|
/**
|
|
* @brief [ActiveRecord] Database Prefix
|
|
*/
|
|
public static $databasePrefix = 'stream_';
|
|
|
|
/**
|
|
* @brief [Node] Order Database Column
|
|
*/
|
|
public static $databaseColumnOrder = 'position';
|
|
|
|
/**
|
|
* Get streams for a member
|
|
*
|
|
* @param \IPS\Member $member The member
|
|
* @return array
|
|
*/
|
|
public static function myStreams( \IPS\Member $member )
|
|
{
|
|
$return = array();
|
|
|
|
foreach ( array( 'open', 'assigned', 'tracked' ) as $k )
|
|
{
|
|
$return[] = static::load( $k );
|
|
}
|
|
|
|
foreach ( new \IPS\Patterns\ActiveRecordIterator( \IPS\Db::i()->select( '*', 'nexus_support_streams', array( 'stream_owner=?', $member->member_id ) ), 'IPS\nexus\Support\Stream' ) as $stream )
|
|
{
|
|
$return[] = $stream;
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Get my stream
|
|
*
|
|
* @return \IPS\nexus\Support\Stream
|
|
*/
|
|
public static function myStream()
|
|
{
|
|
$streamId = isset( \IPS\Request::i()->cookie['support_stream'] ) ? \IPS\Request::i()->cookie['support_stream'] : 'open';
|
|
try
|
|
{
|
|
$stream = \IPS\nexus\Support\Stream::load( $streamId );
|
|
}
|
|
catch ( \OutOfRangeException $e )
|
|
{
|
|
$stream = \IPS\nexus\Support\Stream::load( 'open' );
|
|
}
|
|
return $stream;
|
|
}
|
|
|
|
/**
|
|
* Load
|
|
*
|
|
* @param mixed $keyOrId The key or ID number
|
|
* @return \IPS\nexus\Support\Stream
|
|
*/
|
|
public static function load( $id, $idField=NULL, $extraWhereClause=NULL )
|
|
{
|
|
switch ( $id )
|
|
{
|
|
case 'open':
|
|
$return = new static;
|
|
$return->id = 'open';
|
|
$return->title = \IPS\Member::loggedIn()->language()->addToStack('support_stream_open');
|
|
$return->departments = NULL;
|
|
$return->statuses = iterator_to_array( \IPS\Db::i()->select( 'status_id', 'nexus_support_statuses', array( 'status_open=1' ) ) );
|
|
$return->severities = NULL;
|
|
$return->staff = NULL;
|
|
$return->from_email = NULL;
|
|
$return->search_term = NULL;
|
|
$return->started = NULL;
|
|
$return->last_new_reply = NULL;
|
|
$return->last_reply = NULL;
|
|
$return->last_staff_reply = NULL;
|
|
$return->tracked = FALSE;
|
|
return $return;
|
|
|
|
case 'assigned':
|
|
$return = new static;
|
|
$return->id = 'assigned';
|
|
$return->title = \IPS\Member::loggedIn()->language()->addToStack('support_stream_assigned');
|
|
$return->departments = NULL;
|
|
$return->statuses = iterator_to_array( \IPS\Db::i()->select( 'status_id', 'nexus_support_statuses', array( 'status_open=1' ) ) );
|
|
$return->severities = NULL;
|
|
$return->staff = 'me';
|
|
$return->from_email = NULL;
|
|
$return->search_term = NULL;
|
|
$return->started = NULL;
|
|
$return->last_new_reply = NULL;
|
|
$return->last_reply = NULL;
|
|
$return->last_staff_reply = NULL;
|
|
$return->tracked = FALSE;
|
|
return $return;
|
|
|
|
case 'tracked':
|
|
$return = new static;
|
|
$return->id = 'tracked';
|
|
$return->title = \IPS\Member::loggedIn()->language()->addToStack('support_stream_tracked');
|
|
$return->departments = NULL;
|
|
$return->statuses = NULL;
|
|
$return->severities = NULL;
|
|
$return->staff = NULL;
|
|
$return->from_email = NULL;
|
|
$return->search_term = NULL;
|
|
$return->started = NULL;
|
|
$return->last_new_reply = NULL;
|
|
$return->last_reply = NULL;
|
|
$return->last_staff_reply = NULL;
|
|
$return->tracked = TRUE;
|
|
return $return;
|
|
|
|
default:
|
|
return parent::load( $id, $idField, $extraWhereClause );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Customer Stream
|
|
*
|
|
* @param \IPS\nexus\Customer $customer The customer
|
|
* @return \IPS\nexus\Support\Stream
|
|
*/
|
|
public static function customer( \IPS\nexus\Customer $customer )
|
|
{
|
|
$return = new static;
|
|
$return->title = sprintf( \IPS\Member::loggedIn()->language()->get( 'members_support_requests' ), $customer->cm_name );
|
|
$return->departments = NULL;
|
|
$return->statuses = NULL;
|
|
$return->severities = NULL;
|
|
$return->staff = NULL;
|
|
$return->from_email = $customer->email;
|
|
$return->search_term = NULL;
|
|
$return->started = NULL;
|
|
$return->last_new_reply = NULL;
|
|
$return->last_reply = NULL;
|
|
$return->last_staff_reply = NULL;
|
|
$return->tracked = FALSE;
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Create from form
|
|
*
|
|
* @param array $values Values from the form
|
|
* @return \IPS\nexus\Support\Stream
|
|
*/
|
|
public static function createFromForm( $values )
|
|
{
|
|
$return = new static;
|
|
$return->updateFromForm( $values );
|
|
$return->temporary = TRUE;
|
|
$return->owner = \IPS\Member::loggedIn()->member_id;
|
|
$return->title = \IPS\Member::loggedIn()->language()->get('stream_default_title');
|
|
$return->save();
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Update from form
|
|
*
|
|
* @param array $values Values from the form
|
|
* @return void
|
|
*/
|
|
public function updateFromForm( $values )
|
|
{
|
|
$this->departments = $values['r_department'] ?: NULL;
|
|
$this->statuses = $values['r_status'] ?: NULL;
|
|
$this->severities = $values['r_severity'] ?: NULL;
|
|
$this->staff = $values['r_staff'] ?: NULL;
|
|
$this->from_email = $values['r_email'] ?: NULL;
|
|
$this->search_term = $values['r_search'] ?: NULL;
|
|
$this->started = $values['r_started'] ?: NULL;
|
|
$this->last_new_reply = $values['r_last_new_reply'] ?: NULL;
|
|
$this->last_reply = $values['r_last_reply'] ?: NULL;
|
|
$this->last_staff_reply = $values['r_last_staff_reply'] ?: NULL;
|
|
$this->tracked = (bool) $values['r_tracked'];
|
|
}
|
|
|
|
/**
|
|
* Convert arrays
|
|
*
|
|
* @param mixed $key Key
|
|
* @return mixed Value from the datastore
|
|
*/
|
|
public function __get( $key )
|
|
{
|
|
$return = parent::__get( $key );
|
|
|
|
if ( $return !== NULL and in_array( $key, array( 'departments', 'statuses', 'severities', 'staff' ) ) and $return !== 'me' )
|
|
{
|
|
$return = explode( ',', $return );
|
|
}
|
|
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Set value in data store
|
|
*
|
|
* @see \IPS\Patterns\ActiveRecord::save
|
|
* @param mixed $key Key
|
|
* @param mixed $value Value
|
|
* @return void
|
|
*/
|
|
public function __set( $key, $value )
|
|
{
|
|
if ( is_array( $value ) and in_array( $key, array( 'departments', 'statuses', 'severities', 'staff' ) ) )
|
|
{
|
|
$value = implode( ',', $value );
|
|
}
|
|
|
|
return parent::__set( $key, $value );
|
|
}
|
|
|
|
/**
|
|
* Get form
|
|
*
|
|
* @param \IPS\nexus\Support\Stream $selectedStream The stream to show as selected
|
|
* @param \IPS\Http\Url $url The URL to submit to
|
|
* @return \IPS\Helpers\Form
|
|
*/
|
|
public function form( Stream $selectedStream = NULL, \IPS\Http\Url $url )
|
|
{
|
|
/* Init */
|
|
$form = new \IPS\Helpers\Form( 'form', 'show_results', $url );
|
|
$form->class = 'ipsForm_vertical';
|
|
|
|
/* Streams */
|
|
$form->addTab('streams');
|
|
$form->add( new \IPS\Helpers\Form\Custom( 'stream', $selectedStream ? $selectedStream->id : 'custom', FALSE, array(
|
|
'getHtml' => function( $input ) {
|
|
return \IPS\Theme::i()->getTemplate('support')->filterFormStream( $input, \IPS\nexus\Support\Stream::myStreams( \IPS\Member::loggedIn() ) );
|
|
}
|
|
) ) );
|
|
|
|
/* Departments */
|
|
$form->addTab('first');
|
|
$departments = array();
|
|
foreach ( \IPS\nexus\Support\Department::departmentsWithPermission() as $department )
|
|
{
|
|
$departments[ $department->_id ] = $department->_title;
|
|
}
|
|
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'r_department', $this->departments ?: array_keys( $departments ), FALSE, array( 'options' => $departments ) ) );
|
|
|
|
/* Statuses */
|
|
$statuses = array();
|
|
$openStatuses = array();
|
|
foreach ( \IPS\nexus\Support\Status::roots() as $status )
|
|
{
|
|
$statuses[ $status->_id ] = $status->_title;
|
|
if ( $status->open )
|
|
{
|
|
$openStatuses[] = $status->_id;
|
|
}
|
|
}
|
|
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'r_status', $this->statuses ?: $openStatuses, FALSE, array( 'options' => $statuses ) ) );
|
|
|
|
/* Severities */
|
|
$form->addTab('second');
|
|
$severities = array();
|
|
foreach ( \IPS\nexus\Support\Severity::roots() as $severity )
|
|
{
|
|
$severities[ $severity->_id ] = $severity->_title;
|
|
}
|
|
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'r_severity', $this->severities ?: array_keys( $severities ), FALSE, array( 'options' => $severities ) ) );
|
|
|
|
/* Assigned To */
|
|
$staff = \IPS\nexus\Support\Request::staff();
|
|
$staff[0] = 'unassigned';
|
|
$form->add( new \IPS\Helpers\Form\CheckboxSet( 'r_staff', $this->staff ?: array_keys( $staff ), FALSE, array( 'options' => $staff ) ) );
|
|
|
|
/* Tracked */
|
|
$form->add( new \IPS\Helpers\Form\YesNo( 'r_tracked', $this->tracked, FALSE ) );
|
|
|
|
/* Customer email */
|
|
$form->addTab('third');
|
|
$form->add( new \IPS\Helpers\Form\Email( 'r_email', $this->from_email ) );
|
|
|
|
/* Search text */
|
|
$form->add( new \IPS\Helpers\Form\Text( 'r_search', $this->search_term ) );
|
|
|
|
/* Time frame */
|
|
$timeFrameOptions = array(
|
|
'getHtml' => function( $input ) {
|
|
return \IPS\Theme::i()->getTemplate('support')->filterFormTime( $input );
|
|
}
|
|
);
|
|
$form->add( new \IPS\Helpers\Form\Custom( 'r_started', $this->started, FALSE, $timeFrameOptions ) );
|
|
$form->add( new \IPS\Helpers\Form\Custom( 'r_last_new_reply', $this->last_new_reply, FALSE, $timeFrameOptions ) );
|
|
$form->add( new \IPS\Helpers\Form\Custom( 'r_last_reply', $this->last_reply, FALSE, $timeFrameOptions ) );
|
|
$form->add( new \IPS\Helpers\Form\Custom( 'r_last_staff_reply', $this->last_staff_reply, FALSE, $timeFrameOptions ) );
|
|
|
|
/* Return */
|
|
return $form;
|
|
}
|
|
|
|
/**
|
|
* Get where clause for results
|
|
*
|
|
* @param $member Staff member, or NULL for no permission restriction
|
|
* @return array
|
|
*/
|
|
public function _whereClause( $member )
|
|
{
|
|
/* Init where clause */
|
|
$where = array();
|
|
|
|
/* Departments */
|
|
$departments = NULL;
|
|
if ( $this->departments )
|
|
{
|
|
if ( $member )
|
|
{
|
|
$departments = array_intersect( $this->departments, array_keys( iterator_to_array( \IPS\nexus\Support\Department::departmentsWithPermission( $member ) ) ) );
|
|
}
|
|
else
|
|
{
|
|
$departments = $this->departments;
|
|
}
|
|
}
|
|
elseif ( $member )
|
|
{
|
|
$departments = array_keys( iterator_to_array( \IPS\nexus\Support\Department::departmentsWithPermission( $member ) ) );
|
|
}
|
|
if ( $departments )
|
|
{
|
|
$where[] = array( \IPS\Db::i()->in( 'r_department', $departments ) );
|
|
}
|
|
|
|
/* Statuses */
|
|
if ( $this->statuses )
|
|
{
|
|
$where[] = array( \IPS\Db::i()->in( 'r_status', $this->statuses ) );
|
|
}
|
|
|
|
/* Severities */
|
|
if ( $this->severities )
|
|
{
|
|
$where[] = array( \IPS\Db::i()->in( 'r_severity', $this->severities ) );
|
|
}
|
|
|
|
/* Staff */
|
|
if ( $this->staff )
|
|
{
|
|
if ( $this->staff === 'me' )
|
|
{
|
|
$where[] = array( 'r_staff=?', $member->member_id );
|
|
}
|
|
else
|
|
{
|
|
$where[] = array( \IPS\Db::i()->in( 'r_staff', $this->staff ) );
|
|
}
|
|
}
|
|
|
|
/* From */
|
|
if ( $this->from_email )
|
|
{
|
|
$fromMember = \IPS\Member::load( $this->from_email, 'email' );
|
|
if ( $fromMember->member_id )
|
|
{
|
|
$where[] = array( '( r_member=? OR r_email=? )', $fromMember->member_id, $fromMember->email );
|
|
}
|
|
else
|
|
{
|
|
$where[] = array( '( r_email=? )', $this->from_email );
|
|
}
|
|
}
|
|
|
|
/* Search term */
|
|
if ( $this->search_term )
|
|
{
|
|
$subQuery= \IPS\Content\Search\Mysql\Query::matchClause('reply_post', $this->search_term);
|
|
$where[] = array( 'r_id IN(?)', \IPS\Db::i()->select( 'reply_request', 'nexus_support_replies', $subQuery ) );
|
|
}
|
|
|
|
/* Tracked? */
|
|
if ( $this->tracked and $member )
|
|
{
|
|
$where[] = array( 'r_id IN(?)', \IPS\Db::i()->select( 'request_id', 'nexus_support_tracker', array( 'member_id=?', $member->member_id ) ) );
|
|
}
|
|
|
|
/* Time limits */
|
|
foreach ( array( 'started', 'last_new_reply', 'last_reply', 'last_staff_reply' ) as $k )
|
|
{
|
|
if ( $this->$k )
|
|
{
|
|
$where[] = array( "r_{$k}<?", time() - ( 3600 * $this->$k ) );
|
|
}
|
|
}
|
|
|
|
/* Return */
|
|
return $where;
|
|
}
|
|
|
|
/**
|
|
* Get count
|
|
*
|
|
* @param $member Staff member, or NULL for no permission restriction
|
|
* @return \IPS\Patterns\ActiveRecordIterator
|
|
*/
|
|
public function count( $member = NULL )
|
|
{
|
|
return \IPS\Db::i()->select( 'COUNT(*)', 'nexus_support_requests', $this->_whereClause( $member ) )->first();
|
|
}
|
|
|
|
/**
|
|
* Get results
|
|
*
|
|
* @param $member Staff member, or NULL for no permission restriction
|
|
* @return \IPS\Patterns\ActiveRecordIterator
|
|
*/
|
|
public function results( $member = NULL, $order='r_id DESC', $page = 1, $perPage = 25 )
|
|
{
|
|
$query = \IPS\Db::i()->select( '*', 'nexus_support_requests', $this->_whereClause( $member ), $order, array( ( $page - 1 ) * $perPage, $perPage ) );
|
|
|
|
if ( mb_strpos( $order, 'dpt_position' ) !== FALSE )
|
|
{
|
|
$query->join( 'nexus_support_staff_dpt_order', 'nexus_support_staff_dpt_order.department_id=r_department AND nexus_support_staff_dpt_order.staff_id=' . $member->member_id );
|
|
$query->join( 'nexus_support_departments', 'dpt_id=r_department' );
|
|
}
|
|
if ( mb_strpos( $order, 'sev_position' ) !== FALSE )
|
|
{
|
|
$query->join( 'nexus_support_severities', 'sev_id=r_severity' );
|
|
}
|
|
|
|
$query->setKeyField('r_id');
|
|
|
|
$results = new \IPS\Patterns\ActiveRecordIterator( $query, 'IPS\nexus\Support\Request' );
|
|
return $results;
|
|
}
|
|
}
|