Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
@@ -12,16 +12,39 @@
|
||||
namespace IPS\nexus;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DomainException;
|
||||
use Exception;
|
||||
use IPS\DateTime;
|
||||
use IPS\Email;
|
||||
use IPS\Helpers\Table\Db;
|
||||
use IPS\Http\Url;
|
||||
use IPS\Member;
|
||||
use IPS\Patterns\ActiveRecord;
|
||||
use IPS\Request;
|
||||
use IPS\Task\Queue\OutOfRangeException;
|
||||
use IPS\Theme;
|
||||
use function defined;
|
||||
use function get_called_class;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use const IPS\Helpers\Table\SEARCH_DATE_RANGE;
|
||||
use const IPS\Helpers\Table\SEARCH_MEMBER;
|
||||
use const IPS\Helpers\Table\SEARCH_NUMERIC;
|
||||
use const IPS\Helpers\Table\SEARCH_SELECT;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payout Model
|
||||
*
|
||||
* @property Customer $member
|
||||
*/
|
||||
abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
abstract class Payout extends ActiveRecord
|
||||
{
|
||||
const STATUS_COMPLETE = 'done';
|
||||
const STATUS_PENDING = 'pend';
|
||||
@@ -31,28 +54,35 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* @brief Multiton Store
|
||||
*/
|
||||
protected static $multitons;
|
||||
protected static array $multitons;
|
||||
|
||||
/**
|
||||
* @brief Database Table
|
||||
*/
|
||||
public static $databaseTable = 'nexus_payouts';
|
||||
public static ?string $databaseTable = 'nexus_payouts';
|
||||
|
||||
/**
|
||||
* @brief Database Prefix
|
||||
*/
|
||||
public static $databasePrefix = 'po_';
|
||||
public static string $databasePrefix = 'po_';
|
||||
|
||||
/**
|
||||
* Construct ActiveRecord from database row
|
||||
*
|
||||
* @param array $data Row from database table
|
||||
* @param bool $updateMultitonStoreIfExists Replace current object in multiton store if it already exists there?
|
||||
* @return static
|
||||
* @param array $data Row from database table
|
||||
* @param bool $updateMultitonStoreIfExists Replace current object in multiton store if it already exists there?
|
||||
* @return static
|
||||
* @throws OutOfRangeException
|
||||
*/
|
||||
public static function constructFromData( $data, $updateMultitonStoreIfExists = TRUE )
|
||||
public static function constructFromData( array $data, bool $updateMultitonStoreIfExists = TRUE ): static
|
||||
{
|
||||
$classname = \IPS\nexus\Gateway::payoutGateways()[ $data['po_gateway'] ];
|
||||
$classname = Gateway::payoutGateways()[ $data['po_gateway'] ];
|
||||
|
||||
/* If the classname doesn't exist, then we can't load this */
|
||||
if( !$classname )
|
||||
{
|
||||
throw new OutOfRangeException;
|
||||
}
|
||||
|
||||
/* Initiate an object */
|
||||
$obj = new $classname;
|
||||
@@ -63,7 +93,7 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
{
|
||||
if( static::$databasePrefix AND mb_strpos( $k, static::$databasePrefix ) === 0 )
|
||||
{
|
||||
$k = \substr( $k, \strlen( static::$databasePrefix ) );
|
||||
$k = substr( $k, strlen( static::$databasePrefix ) );
|
||||
}
|
||||
|
||||
$obj->_data[ $k ] = $v;
|
||||
@@ -79,69 +109,68 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultValues()
|
||||
public function setDefaultValues() : void
|
||||
{
|
||||
$this->date = new \IPS\DateTime;
|
||||
$this->date = new DateTime;
|
||||
$this->status = static::STATUS_PENDING;
|
||||
$this->gateway = preg_replace( '/.+?\\\([A-Z]+?)\\\Payout$/i', '$1', \get_called_class() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Requires manual approval?
|
||||
*/
|
||||
public static $requiresApproval = FALSE;
|
||||
public static bool $requiresApproval = FALSE;
|
||||
|
||||
/**
|
||||
* Get payouts table
|
||||
*
|
||||
* @param array $where Where clause
|
||||
* @param \IPS\Http\Url $ref URL to display table on
|
||||
* @return \IPS\Helpers\Table\Db
|
||||
* @param Url $url URL to display table on
|
||||
* @return Db
|
||||
*/
|
||||
public static function table( $where, \IPS\Http\Url $url )
|
||||
public static function table( array $where, Url $url ) : Db
|
||||
{
|
||||
$table = new \IPS\Helpers\Table\Db( 'nexus_payouts', $url, $where );
|
||||
$table = new Db( 'nexus_payouts', $url, $where );
|
||||
$table->include = array( 'po_status', 'po_id', 'po_gateway', 'po_member', 'po_amount', 'po_date' );
|
||||
$table->parsers = array(
|
||||
'po_status' => function( $val )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate( 'payouts', 'nexus' )->status( $val );
|
||||
return Theme::i()->getTemplate( 'payouts', 'nexus' )->status( $val );
|
||||
},
|
||||
'po_member' => function ( $val, $row )
|
||||
'po_member' => function ( $val )
|
||||
{
|
||||
return \IPS\Theme::i()->getTemplate('global')->userLink( \IPS\Member::load( $val ) );
|
||||
return Theme::i()->getTemplate('global')->userLink( Member::load( $val ) );
|
||||
},
|
||||
'po_amount' => function( $val, $row )
|
||||
{
|
||||
return (string) new \IPS\nexus\Money( $val, $row['po_currency'] );
|
||||
return (string) new Money( $val, $row['po_currency'] );
|
||||
},
|
||||
'po_date' => function( $val )
|
||||
{
|
||||
return \IPS\DateTime::ts( $val );
|
||||
return DateTime::ts( $val );
|
||||
}
|
||||
);
|
||||
$table->filters = array(
|
||||
'postatus_pend' => array( 'po_status=?', 'pend' ),
|
||||
);
|
||||
$table->advancedSearch = array(
|
||||
'po_status' => array( \IPS\Helpers\Table\SEARCH_SELECT, array( 'options' => array(
|
||||
\IPS\nexus\Payout::STATUS_COMPLETE => 'postatus_' . \IPS\nexus\Payout::STATUS_COMPLETE,
|
||||
\IPS\nexus\Payout::STATUS_PENDING => 'postatus_' . \IPS\nexus\Payout::STATUS_PENDING,
|
||||
\IPS\nexus\Payout::STATUS_CANCELED => 'postatus_' . \IPS\nexus\Payout::STATUS_CANCELED,
|
||||
'po_status' => array( SEARCH_SELECT, array( 'options' => array(
|
||||
Payout::STATUS_COMPLETE => 'postatus_' . Payout::STATUS_COMPLETE,
|
||||
Payout::STATUS_PENDING => 'postatus_' . Payout::STATUS_PENDING,
|
||||
Payout::STATUS_CANCELED => 'postatus_' . Payout::STATUS_CANCELED,
|
||||
), 'multiple' => TRUE ) ),
|
||||
'po_member' => \IPS\Helpers\Table\SEARCH_MEMBER,
|
||||
'po_amount' => \IPS\Helpers\Table\SEARCH_NUMERIC,
|
||||
'po_date' => \IPS\Helpers\Table\SEARCH_DATE_RANGE,
|
||||
'po_member' => SEARCH_MEMBER,
|
||||
'po_amount' => SEARCH_NUMERIC,
|
||||
'po_date' => SEARCH_DATE_RANGE,
|
||||
);
|
||||
$table->rowButtons = function( $row )
|
||||
{
|
||||
return array_merge( array(
|
||||
'view' => array(
|
||||
'icon' => 'search',
|
||||
'link' => \IPS\Http\Url::internal( "app=nexus&module=payments&controller=payouts&do=view&id={$row['po_id']}" ),
|
||||
'link' => Url::internal( "app=nexus&module=payments&controller=payouts&do=view&id={$row['po_id']}" ),
|
||||
'title' => 'view',
|
||||
),
|
||||
), \IPS\nexus\Payout::constructFromData( $row )->buttons( 't' ) );
|
||||
), Payout::constructFromData( $row )->buttons( 't' ) );
|
||||
};
|
||||
$table->sortBy = $table->sortBy ?: 'po_date';
|
||||
|
||||
@@ -151,20 +180,20 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Get amount
|
||||
*
|
||||
* @return \IPS\nexus\Money
|
||||
* @return Money
|
||||
*/
|
||||
public function get_amount()
|
||||
public function get_amount() : Money
|
||||
{
|
||||
return new \IPS\nexus\Money( $this->_data['amount'], $this->_data['currency'] );
|
||||
return new Money( $this->_data['amount'], $this->_data['currency'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set amount
|
||||
*
|
||||
* @param \IPS\nexus\Money $amount The total
|
||||
* @param Money $amount The total
|
||||
* @return void
|
||||
*/
|
||||
public function set_amount( \IPS\nexus\Money $amount )
|
||||
public function set_amount(Money $amount ) : void
|
||||
{
|
||||
$this->_data['amount'] = $amount->amount;
|
||||
$this->_data['currency'] = $amount->currency;
|
||||
@@ -173,20 +202,20 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Get member
|
||||
*
|
||||
* @return \IPS\Member
|
||||
* @return Customer
|
||||
*/
|
||||
public function get_member()
|
||||
public function get_member() : Customer
|
||||
{
|
||||
return \IPS\nexus\Customer::load( $this->_data['member'] );
|
||||
return Customer::load( $this->_data['member'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set member
|
||||
*
|
||||
* @param \IPS\Member
|
||||
* @param Member $member
|
||||
* @return void
|
||||
*/
|
||||
public function set_member( \IPS\Member $member )
|
||||
public function set_member( Member $member ) : void
|
||||
{
|
||||
$this->_data['member'] = $member->member_id;
|
||||
}
|
||||
@@ -194,20 +223,20 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Get date
|
||||
*
|
||||
* @return \IPS\DateTime
|
||||
* @return DateTime
|
||||
*/
|
||||
public function get_date()
|
||||
public function get_date() : DateTime
|
||||
{
|
||||
return \IPS\DateTime::ts( $this->_data['date'] );
|
||||
return DateTime::ts( $this->_data['date'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set date
|
||||
*
|
||||
* @param \IPS\DateTime $date The invoice date
|
||||
* @param DateTime $date The invoice date
|
||||
* @return void
|
||||
*/
|
||||
public function set_date( \IPS\DateTime $date )
|
||||
public function set_date( DateTime $date ) : void
|
||||
{
|
||||
$this->_data['date'] = $date->getTimestamp();
|
||||
}
|
||||
@@ -215,20 +244,20 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Get completed date
|
||||
*
|
||||
* @return \IPS\DateTime|NULL
|
||||
* @return DateTime|NULL
|
||||
*/
|
||||
public function get_completed()
|
||||
public function get_completed() : DateTime|null
|
||||
{
|
||||
return $this->_data['completed'] ? \IPS\DateTime::ts( $this->_data['completed'] ) : NULL;
|
||||
return $this->_data['completed'] ? DateTime::ts( $this->_data['completed'] ) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set completed date
|
||||
*
|
||||
* @param \IPS\DateTime $date The invoice date
|
||||
* @param DateTime $date The invoice date
|
||||
* @return void
|
||||
*/
|
||||
public function set_completed( \IPS\DateTime $date )
|
||||
public function set_completed( DateTime $date ) : void
|
||||
{
|
||||
$this->_data['completed'] = $date->getTimestamp();
|
||||
}
|
||||
@@ -236,20 +265,20 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* Get approving member
|
||||
*
|
||||
* @return \IPS\Member
|
||||
* @return Customer|null
|
||||
*/
|
||||
public function get_processed_by()
|
||||
public function get_processed_by() : Customer|null
|
||||
{
|
||||
return $this->_data['processed_by'] ? \IPS\nexus\Customer::load( $this->_data['processed_by'] ) : NULL;
|
||||
return $this->_data['processed_by'] ? Customer::load( $this->_data['processed_by'] ) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set approving member
|
||||
*
|
||||
* @param \IPS\Member
|
||||
* @param Member $member
|
||||
* @return void
|
||||
*/
|
||||
public function set_processed_by( \IPS\Member $member )
|
||||
public function set_processed_by( Member $member ) : void
|
||||
{
|
||||
$this->_data['processed_by'] = $member->member_id;
|
||||
}
|
||||
@@ -260,14 +289,15 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
* @param string $ref Referer
|
||||
* @return array
|
||||
*/
|
||||
public function buttons( $ref='v' )
|
||||
public function buttons( string $ref='v' ) : array
|
||||
{
|
||||
$url = $this->acpUrl()->setQueryString( array( 'r' => $ref, 'filter' => \IPS\Request::i()->filter ) );
|
||||
/* @var Url\Internal $url */
|
||||
$url = $this->acpUrl()->setQueryString( array( 'r' => $ref, 'filter' => Request::i()->filter ) );
|
||||
$return = array();
|
||||
|
||||
if ( $this->status === static::STATUS_PENDING )
|
||||
{
|
||||
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'payouts_process' ) )
|
||||
if( Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'payouts_process' ) )
|
||||
{
|
||||
$return['approve'] = array(
|
||||
'title' => 'approve',
|
||||
@@ -276,7 +306,7 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
'data' => array( 'confirm' => '' )
|
||||
);
|
||||
}
|
||||
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'payouts_cancel' ) )
|
||||
if( Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'payouts_cancel' ) )
|
||||
{
|
||||
$return['cancel'] = array(
|
||||
'title' => 'cancel',
|
||||
@@ -284,20 +314,20 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
'link' => $url->setQueryString( 'do', 'cancel' )->csrf(),
|
||||
'data' => array(
|
||||
'confirm' => '',
|
||||
'confirmMessage' => \IPS\Member::loggedIn()->language()->addToStack('payout_cancel_confirm'),
|
||||
'confirmMessage' => Member::loggedIn()->language()->addToStack('payout_cancel_confirm'),
|
||||
'confirmType' => 'verify',
|
||||
'confirmIcon' => 'question',
|
||||
'confirmButtons' => json_encode( array(
|
||||
'yes' => \IPS\Member::loggedIn()->language()->addToStack('yes'),
|
||||
'no' => \IPS\Member::loggedIn()->language()->addToStack('no'),
|
||||
'cancel' => \IPS\Member::loggedIn()->language()->addToStack('cancel'),
|
||||
'yes' => Member::loggedIn()->language()->addToStack('yes'),
|
||||
'no' => Member::loggedIn()->language()->addToStack('no'),
|
||||
'cancel' => Member::loggedIn()->language()->addToStack('cancel'),
|
||||
) )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if( \IPS\Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'payouts_delete' ) )
|
||||
if( Member::loggedIn()->hasAcpRestriction( 'nexus', 'payments', 'payouts_delete' ) )
|
||||
{
|
||||
$return['delete'] = array(
|
||||
'title' => 'delete',
|
||||
@@ -313,11 +343,21 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
/**
|
||||
* ACP URL
|
||||
*
|
||||
* @return \IPS\Http\Url
|
||||
* @return Url
|
||||
*/
|
||||
public function acpUrl()
|
||||
public function acpUrl() : Url
|
||||
{
|
||||
return \IPS\Http\Url::internal( "app=nexus&module=payments&controller=payouts&do=view&id={$this->id}", 'admin' );
|
||||
return Url::internal( "app=nexus&module=payments&controller=payouts&do=view&id={$this->id}", 'admin' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra HTML to display when the admin view the Payout in the ACP
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function acpHtml() : string
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,20 +367,76 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function markCompleted()
|
||||
public function markCompleted() : void
|
||||
{
|
||||
$this->status = static::STATUS_COMPLETE;
|
||||
$this->completed = new \IPS\DateTime;
|
||||
$this->completed = new DateTime;
|
||||
$this->save();
|
||||
|
||||
/* Notify member */
|
||||
\IPS\Email::buildFromTemplate( 'nexus', 'payoutComplete', array( $this ), \IPS\Email::TYPE_TRANSACTIONAL )->send( $this->member );
|
||||
Email::buildFromTemplate( 'nexus', 'payoutComplete', array( $this ), Email::TYPE_TRANSACTIONAL )->send( $this->member );
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Changed Columns
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function save(): void
|
||||
{
|
||||
if( $this->_new )
|
||||
{
|
||||
/* Find the gateway key based on the class we called */
|
||||
$class = get_called_class();
|
||||
foreach( Gateway::payoutGateways() as $k => $v )
|
||||
{
|
||||
if( $v == $class )
|
||||
{
|
||||
$this->gateway = $k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parent::save();
|
||||
}
|
||||
|
||||
/**
|
||||
* ACP Settings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public static function settings() : array;
|
||||
|
||||
/**
|
||||
* Payout Form
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public static function form() :array;
|
||||
|
||||
/**
|
||||
* Get data and validate
|
||||
*
|
||||
* @param array $values Values from form
|
||||
* @return mixed
|
||||
* @throws DomainException
|
||||
*/
|
||||
abstract public function getData( array $values ) : mixed;
|
||||
|
||||
/**
|
||||
* Process the payout
|
||||
* Return the new status for this payout record
|
||||
*
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
abstract public function process() : string;
|
||||
|
||||
/**
|
||||
* Get output for API
|
||||
*
|
||||
* @param \IPS\Member|NULL $authorizedMember The member making the API request or NULL for API Key / client_credentials
|
||||
* @param Member|NULL $authorizedMember The member making the API request or NULL for API Key / client_credentials
|
||||
* @return array
|
||||
* @apiresponse int id ID number
|
||||
* @apiresponse string status Status: 'done' = Payment sent; 'pend' = Pending; 'canc' = Canceled
|
||||
@@ -352,7 +448,7 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
* @clientapiresponse string gatewayId Any ID number provided by the gateway to identify the transaction on their end
|
||||
* @apiresponse \IPS\nexus\Customer customer Customer
|
||||
*/
|
||||
public function apiOutput( \IPS\Member $authorizedMember = NULL )
|
||||
public function apiOutput( ?Member $authorizedMember = NULL ): array
|
||||
{
|
||||
return array(
|
||||
'id' => $this->id,
|
||||
@@ -362,7 +458,7 @@ abstract class _Payout extends \IPS\Patterns\ActiveRecord
|
||||
'gateway' => $this->gateway,
|
||||
'data' => $this->data,
|
||||
'requestedDate' => $this->date->rfc3339(),
|
||||
'completedDate' => $this->completed ? $this->completed->rfc3339() : null,
|
||||
'completedDate' => $this->completed?->rfc3339(),
|
||||
'gatewayId' => $this->gw_id,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user