installed plugin Easy Digital Downloads
version 3.1.0.3
This commit is contained in:
@ -0,0 +1,288 @@
|
||||
<?php
|
||||
/**
|
||||
* Download.php
|
||||
*
|
||||
* @package easy-digital-downloads
|
||||
* @copyright Copyright (c) 2022, Easy Digital Downloads
|
||||
* @license GPL2+
|
||||
* @since 3.0
|
||||
*/
|
||||
|
||||
namespace EDD\Models;
|
||||
|
||||
class Download {
|
||||
|
||||
/**
|
||||
* The download ID.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* The price ID.
|
||||
*
|
||||
* @var null|int
|
||||
*/
|
||||
public $price_id = null;
|
||||
|
||||
/**
|
||||
* Optional additional parameters that can be passed to the model.
|
||||
*
|
||||
* @since 3.0
|
||||
* @var array
|
||||
*/
|
||||
public $args = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $id The download ID.
|
||||
*/
|
||||
public function __construct( $id, $price_id = null, $args = array() ) {
|
||||
$this->id = $id;
|
||||
$this->price_id = $price_id;
|
||||
$this->args = $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the gross number of sales for this download from the database.
|
||||
*
|
||||
* @since 3.0
|
||||
* @return int
|
||||
*/
|
||||
public function get_gross_sales() {
|
||||
global $wpdb;
|
||||
|
||||
$product_id_sql = $this->generate_product_id_query_sql();
|
||||
$price_id_sql = $this->generate_price_id_query_sql();
|
||||
$order_status_sql = $this->generate_order_status_query_sql( false );
|
||||
$date_query_sql = $this->generate_date_query_sql();
|
||||
|
||||
$results = $wpdb->get_row(
|
||||
"SELECT SUM(oi.quantity) AS sales
|
||||
FROM {$wpdb->edd_order_items} oi
|
||||
INNER JOIN {$wpdb->edd_orders} o ON(o.id = oi.order_id)
|
||||
WHERE {$product_id_sql}
|
||||
{$price_id_sql}
|
||||
AND o.type = 'sale'
|
||||
{$order_status_sql}
|
||||
{$date_query_sql}"
|
||||
);
|
||||
|
||||
return ! empty( $results->sales ) ? intval( $results->sales ) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the gross earnings for this download from the database.
|
||||
*
|
||||
* @since 3.0
|
||||
* @return float
|
||||
*/
|
||||
public function get_gross_earnings() {
|
||||
global $wpdb;
|
||||
|
||||
$product_id_sql = $this->generate_product_id_query_sql();
|
||||
$price_id_sql = $this->generate_price_id_query_sql();
|
||||
$order_status_sql = $this->generate_order_status_query_sql( false );
|
||||
$date_query_sql = $this->generate_date_query_sql();
|
||||
|
||||
$order_items =
|
||||
"SELECT SUM(oi.subtotal / oi.rate) AS revenue
|
||||
FROM {$wpdb->edd_order_items} oi
|
||||
INNER JOIN {$wpdb->edd_orders} o ON(o.id = oi.order_id)
|
||||
WHERE {$product_id_sql}
|
||||
{$price_id_sql}
|
||||
AND o.type = 'sale'
|
||||
{$order_status_sql}
|
||||
{$date_query_sql}";
|
||||
// Fees on order items count as part of gross revenue.
|
||||
$order_adjustments =
|
||||
"SELECT SUM(oa.subtotal/ oa.rate) as revenue
|
||||
FROM {$wpdb->edd_order_adjustments} oa
|
||||
INNER JOIN {$wpdb->edd_order_items} oi ON(oi.id = oa.object_id)
|
||||
WHERE {$product_id_sql}
|
||||
{$price_id_sql}
|
||||
AND oa.object_type = 'order_item'
|
||||
AND oa.type != 'discount'
|
||||
AND oa.total > 0
|
||||
{$date_query_sql}";
|
||||
|
||||
$results = $wpdb->get_row( "SELECT SUM(revenue) AS revenue FROM ({$order_items} UNION {$order_adjustments})a" );
|
||||
|
||||
return ! empty( $results->revenue ) ? floatval( edd_sanitize_amount( $results->revenue ) ) : 0.00;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the net number of sales for this download from the database.
|
||||
* Because a partial refund with an identical quantity as the original order will
|
||||
* negate the original, we also sum partially refunded sales where the quantity
|
||||
* matches the partial refund quantity.
|
||||
*
|
||||
* @since 3.0
|
||||
* @return int
|
||||
*/
|
||||
public function get_net_sales() {
|
||||
global $wpdb;
|
||||
|
||||
$product_id_sql = $this->generate_product_id_query_sql();
|
||||
$price_id_sql = $this->generate_price_id_query_sql();
|
||||
$order_status_sql = $this->generate_order_status_query_sql();
|
||||
$date_query_sql = $this->generate_date_query_sql();
|
||||
|
||||
$complete_orders =
|
||||
"SELECT SUM(oi.quantity) as sales
|
||||
FROM {$wpdb->edd_order_items} oi
|
||||
INNER JOIN {$wpdb->edd_orders} o ON(o.id = oi.order_id)
|
||||
WHERE {$product_id_sql}
|
||||
{$price_id_sql}
|
||||
AND oi.status IN('complete','refunded','partially_refunded')
|
||||
{$order_status_sql} {$date_query_sql}";
|
||||
$partial_orders =
|
||||
"SELECT SUM(oi.quantity) as sales
|
||||
FROM {$wpdb->edd_order_items} oi
|
||||
LEFT JOIN {$wpdb->edd_order_items} ri
|
||||
ON ri.parent = oi.id
|
||||
WHERE {$product_id_sql}
|
||||
{$price_id_sql}
|
||||
AND oi.status = 'partially_refunded'
|
||||
AND oi.quantity = - ri.quantity
|
||||
{$date_query_sql}";
|
||||
|
||||
$results = $wpdb->get_row( "SELECT SUM(sales) AS sales FROM ({$complete_orders} UNION {$partial_orders})a" );
|
||||
|
||||
return ! empty( $results->sales ) ? $results->sales : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the net earnings for this download from the database.
|
||||
*
|
||||
* @since 3.0
|
||||
* @return float
|
||||
*/
|
||||
public function get_net_earnings() {
|
||||
global $wpdb;
|
||||
|
||||
$product_id_sql = $this->generate_product_id_query_sql();
|
||||
$price_id_sql = $this->generate_price_id_query_sql();
|
||||
$order_status_sql = $this->generate_order_status_query_sql( false );
|
||||
$date_query_sql = $this->generate_date_query_sql();
|
||||
|
||||
/**
|
||||
* Note on the select statements:
|
||||
* 1. This gets the net sum for revenue and sales for all orders with net statuses.
|
||||
* 2. Because a partial refund with an identical quantity as the original order will
|
||||
* negate the original, we also sum partially refunded sales where the quantity
|
||||
* matches the partial refund quantity.
|
||||
*/
|
||||
$order_items =
|
||||
"SELECT SUM((oi.total - oi.tax)/ oi.rate) as revenue
|
||||
FROM {$wpdb->edd_order_items} oi
|
||||
INNER JOIN {$wpdb->edd_orders} o ON(o.id = oi.order_id)
|
||||
WHERE {$product_id_sql}
|
||||
{$price_id_sql}
|
||||
AND oi.status IN('complete','partially_refunded','refunded')
|
||||
{$order_status_sql} {$date_query_sql}";
|
||||
$order_adjustments =
|
||||
"SELECT SUM((oa.total - oa.tax)/ oa.rate) as revenue
|
||||
FROM {$wpdb->edd_order_adjustments} oa
|
||||
INNER JOIN {$wpdb->edd_order_items} oi ON(oi.id = oa.object_id)
|
||||
WHERE {$product_id_sql}
|
||||
{$price_id_sql}
|
||||
AND oa.object_type = 'order_item'
|
||||
AND oa.type != 'discount'
|
||||
AND oi.status IN('complete','partially_refunded')
|
||||
{$date_query_sql}";
|
||||
|
||||
$results = $wpdb->get_row( "SELECT SUM(revenue) AS revenue FROM ({$order_items} UNION {$order_adjustments})a" );
|
||||
|
||||
return ! empty( $results->revenue ) ? $results->revenue : 0.00;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array of statuses to a string for a SQL query.
|
||||
*
|
||||
* @since 3.0
|
||||
* @param array $statuses
|
||||
* @return string
|
||||
*/
|
||||
private function convert_status_array_to_string( $statuses ) {
|
||||
return implode( ', ', array_fill( 0, count( $statuses ), '%s' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the query string for the product ID.
|
||||
*
|
||||
* @since 3.0
|
||||
* @return string
|
||||
*/
|
||||
private function generate_product_id_query_sql() {
|
||||
global $wpdb;
|
||||
|
||||
return $wpdb->prepare(
|
||||
'oi.product_id = %d',
|
||||
$this->id
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the query string for a product price ID.
|
||||
*
|
||||
* @since 3.0
|
||||
* @return string
|
||||
*/
|
||||
private function generate_price_id_query_sql() {
|
||||
if ( is_null( $this->price_id ) || ! is_numeric( $this->price_id ) ) {
|
||||
return '';
|
||||
}
|
||||
global $wpdb;
|
||||
|
||||
return $wpdb->prepare( 'AND oi.price_id = %d', $this->price_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the query string for the order statuses.
|
||||
*
|
||||
* @since 3.0
|
||||
* @param bool $net Whether to use net statuses.
|
||||
* @return string
|
||||
*/
|
||||
private function generate_order_status_query_sql( $net = true ) {
|
||||
global $wpdb;
|
||||
$statuses = $net ? edd_get_net_order_statuses() : edd_get_gross_order_statuses();
|
||||
|
||||
return $wpdb->prepare(
|
||||
"AND o.status IN({$this->convert_status_array_to_string( $statuses )})",
|
||||
...$statuses
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the query string for the dates, if set.
|
||||
*
|
||||
* @since 3.0
|
||||
* @return string
|
||||
*/
|
||||
private function generate_date_query_sql() {
|
||||
if ( empty( $this->args['start'] ) && empty( $this->args['end'] ) ) {
|
||||
return '';
|
||||
}
|
||||
global $wpdb;
|
||||
$date_query_sql = ' AND ';
|
||||
|
||||
if ( ! empty( $this->args['start'] ) ) {
|
||||
$date_query_sql .= $wpdb->prepare( 'oi.date_created >= %s', $this->args['start'] );
|
||||
}
|
||||
|
||||
// Join dates with `AND` if start and end date set.
|
||||
if ( ! empty( $this->args['start'] ) && ! empty( $this->args['end'] ) ) {
|
||||
$date_query_sql .= ' AND ';
|
||||
}
|
||||
|
||||
if ( ! empty( $this->args['end'] ) ) {
|
||||
$date_query_sql .= $wpdb->prepare( 'oi.date_created <= %s', $this->args['end'] );
|
||||
}
|
||||
|
||||
return $date_query_sql;
|
||||
}
|
||||
}
|
@ -0,0 +1,192 @@
|
||||
<?php
|
||||
/**
|
||||
* Notification.php
|
||||
*
|
||||
* @package easy-digital-downloads
|
||||
* @copyright Copyright (c) 2021, Easy Digital Downloads
|
||||
* @license GPL2+
|
||||
* @since 2.11.4
|
||||
*/
|
||||
|
||||
namespace EDD\Models;
|
||||
|
||||
class Notification {
|
||||
|
||||
/**
|
||||
* @var int Unique internal ID.
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @var null|int ID from the remote feed. If `null` then this notification was added internally
|
||||
* and not via the remote import.
|
||||
*/
|
||||
public $remote_id = null;
|
||||
|
||||
/**
|
||||
* @var string Title of the notification.
|
||||
*/
|
||||
public $title;
|
||||
|
||||
/**
|
||||
* @var string Notification content.
|
||||
*/
|
||||
public $content;
|
||||
|
||||
/**
|
||||
* @var array|null Button information, if set.
|
||||
*/
|
||||
public $buttons;
|
||||
|
||||
/**
|
||||
* @var string Notification type, including: `warning`, `error`, `info`, or `success`.
|
||||
*/
|
||||
public $type;
|
||||
|
||||
/**
|
||||
* @var array|null Conditions that must be met to display this notification. If `null`
|
||||
* then there are no conditions.
|
||||
*/
|
||||
public $conditions = null;
|
||||
|
||||
/**
|
||||
* @var null|string Date to start displaying the notification.
|
||||
*/
|
||||
public $start = null;
|
||||
|
||||
/**
|
||||
* @var null|string Date to stop displaying the notification.
|
||||
*/
|
||||
public $end = null;
|
||||
|
||||
/**
|
||||
* @var bool Whether this notification has been dismissed by the user.
|
||||
*/
|
||||
public $dismissed = false;
|
||||
|
||||
/**
|
||||
* @var string Date the notification was added to the database.
|
||||
*/
|
||||
public $date_created;
|
||||
|
||||
/**
|
||||
* @var string Date the notification was last updated in the database.
|
||||
*/
|
||||
public $date_updated;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $casts = array(
|
||||
'id' => 'int',
|
||||
'remote_id' => 'int',
|
||||
'buttons' => 'array',
|
||||
'conditions' => 'array',
|
||||
'dismissed' => 'bool',
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array $data Row from the database.
|
||||
*/
|
||||
public function __construct( $data = array() ) {
|
||||
foreach ( $data as $property => $value ) {
|
||||
if ( property_exists( $this, $property ) ) {
|
||||
$this->{$property} = $this->castAttribute( $property, $value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts a property to its designated type.
|
||||
*
|
||||
* @todo Move to trait or base class.
|
||||
*
|
||||
* @since 2.11.4
|
||||
*
|
||||
* @param string $propertyName
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool|float|int|mixed|string|null
|
||||
*/
|
||||
private function castAttribute( $propertyName, $value ) {
|
||||
if ( ! array_key_exists( $propertyName, $this->casts ) ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// Let null be null.
|
||||
if ( is_null( $value ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch ( $this->casts[ $propertyName ] ) {
|
||||
case 'array' :
|
||||
return json_decode( $value, true );
|
||||
case 'bool' :
|
||||
return (bool) $value;
|
||||
case 'float' :
|
||||
return (float) $value;
|
||||
case 'int' :
|
||||
return (int) $value;
|
||||
case 'string' :
|
||||
return (string) $value;
|
||||
default :
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the icon name to use for this notification type.
|
||||
*
|
||||
* @since 2.11.4
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIcon() {
|
||||
switch ( $this->type ) {
|
||||
case 'warning' :
|
||||
return 'warning';
|
||||
case 'error' :
|
||||
return 'dismiss';
|
||||
case 'info' :
|
||||
return 'admin-generic';
|
||||
case 'success' :
|
||||
default :
|
||||
return 'yes-alt';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this model to an array.
|
||||
*
|
||||
* @todo Move to trait.
|
||||
*
|
||||
* @since 2.11.4
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray() {
|
||||
$data = array();
|
||||
|
||||
/*
|
||||
* get_object_vars() returns non-public properties when used within the class
|
||||
* so we're using a ReflectionClass to get the public properties only.
|
||||
*/
|
||||
$object = new \ReflectionClass( $this );
|
||||
|
||||
foreach ( $object->getProperties( \ReflectionProperty::IS_PUBLIC ) as $property ) {
|
||||
if ( $property instanceof \ReflectionProperty && isset( $this->{$property->name} ) ) {
|
||||
$data[ $property->name ] = $this->{$property->name};
|
||||
}
|
||||
}
|
||||
|
||||
$data['icon_name'] = $this->getIcon();
|
||||
|
||||
/* Translators: %s - a length of time (e.g. "1 second") */
|
||||
$data['relative_date'] = sprintf( __( '%s ago', 'easy-digital-downloads' ), human_time_diff( strtotime( $this->date_created ) ) );
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user