first commit

This commit is contained in:
2024-07-15 11:28:08 +02:00
commit f52d538ea5
21891 changed files with 6161164 additions and 0 deletions

View File

@@ -0,0 +1,146 @@
<?php
/**
* File that define P24_Subscription_Admin class.
*
* @package Przelewy24
*/
defined( 'ABSPATH' ) || exit;
/**
* Class P24_Subscription_Admin
*/
class P24_Subscription_Admin {
/**
* The P24_Core instance.
*
* @var P24_Core
*/
private $plugin_core;
/**
* The constructor.
*
* @param P24_Core $plugin_core The P24_Core instance.
*/
public function __construct( P24_Core $plugin_core ) {
$this->plugin_core = $plugin_core;
}
/**
* Try serve csv.
*/
public function try_serve_csv() {
/* User credenitals should be checked and high enough. */
wp_verify_nonce( null );
if ( isset( $_GET['p24'] ) && isset( $_GET['subscription_csv'] ) ) {
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename=p24_subscriptions.csv' );
$header = array(
__( 'Użytkownik' ),
__( 'E-Mail' ),
__( 'Ważna do' ),
__( 'Subskrypcje' ),
);
$list = P24_Subscription_Db::get_active_list();
$stdout = fopen( 'php://output', 'w' );
fputcsv( $stdout, $header );
foreach ( $list as $one ) {
$array = (array) $one;
fputcsv( $stdout, $array );
}
exit();
}
}
/**
* Add P24 subscription tab.
*
* @param array $tabs Provided tabs.
* @return array Extended tabs.
*/
public function add_subscription_tab( $tabs ) {
$new_tabs = array(
/* This one has to be first. */
'general' => $tabs['general'],
'p24_subscription' => array(
'label' => __( 'Ustawienia subskrypcji' ),
'target' => 'p24_subscription_options',
'class' => ( 'show_if_p24_subscription' ),
),
);
return $new_tabs + $tabs;
}
/**
* Parse cancellation request.
*/
public static function parse_cancellation_request() {
$ok = wp_verify_nonce( isset( $_POST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ) : null, 'p24_subscription' );
if ( $ok ) {
self::parse_cancellation_request_internal( $_POST );
}
}
/**
* Parse cancellation request internal.
*
* @param array $data The post data.
*/
private static function parse_cancellation_request_internal( $data ) {
if ( ! isset( $data['displayed'] ) ) {
/* Nothing to do. */
return;
}
$a = $data['displayed'];
if ( isset( $data['preserve'] ) ) {
$b = $data['preserve'];
} else {
$b = array();
}
$todel = array_diff( $a, $b );
foreach ( $todel as $one ) {
$one = (int) $one;
if ( $one ) {
$ok = P24_Subscription_Db::end_subscription( $one );
if ( $ok ) {
$data = P24_Subscription_Db::get_extended_data_for_single( $one );
self::send_email_about_cancellation( $data );
}
}
}
}
/**
* Send email about cancellation.
*
* @param array $data Data from database.
*/
private static function send_email_about_cancellation( $data ) {
if ( ! $data ) {
return;
}
$mailer = WC()->mailer();
$subject = __( 'Twoja subskrypcja została anulowana', 'przelewy24' );
$args = array(
'email_heading' => $subject,
'subscription_title' => $data['subscription_title'],
'email' => $mailer,
);
$headers = 'Content-Type: text/html';
$dir = __DIR__ . '/../../emails/';
$content = wc_get_template_html( 'subscription-cancellation.php', $args, $dir, $dir );
$mailer->send( $data['user_email'], $subject, $content, $headers );
}
/**
* Bind events.
*/
public function bind_core_events() {
add_filter( 'woocommerce_product_data_tabs', array( $this, 'add_subscription_tab' ) );
add_action( 'admin_init', array( $this, 'try_serve_csv' ) );
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* File that define P24_Subscription_Api class.
*
* @package Przelewy24
*/
defined( 'ABSPATH' ) || exit;
/**
* Class P24_Subscription_Api
*/
class P24_Subscription_Api {
/**
* Query db.
*
* @param int|null $for_user User id.
* @param int|null $subscription Subcription (product) id.
* @return array
*/
private static function query_db( $for_user, $subscription ) {
global $wpdb;
$now = new DateTime();
$for_user = (int) $for_user;
$subscription = (int) $subscription;
$list = $wpdb->get_results(
$wpdb->prepare(
"
SELECT
u.ID AS user_id,
u.user_nicename,
u.user_email,
s.valid_to,
p.ID AS subscription_id,
p.post_title AS subscription_title
FROM {$wpdb->prefix}woocommerce_p24_subscription AS s
INNER JOIN {$wpdb->prefix}posts AS p ON p.ID = s.product_id
INNER JOIN {$wpdb->prefix}users AS u ON u.ID = s.user_id
WHERE s.valid_to > %s
AND (u.ID = %d OR 0 = %d)
AND (p.ID = %d OR 0 = %d)
ORDER BY p.post_title, u.user_email, s.id
;
",
array(
$now->format( 'Y-m-d H:i:s' ),
$for_user, /* The variable is used twice. */
$for_user,
$subscription, /* The variable is used twice. */
$subscription,
)
)
); /* db call ok; no cache ok */
return $list;
}
/**
* Try serve JSON.
*/
public function try_serve() {
/* User credentials should be checked and high enough. */
wp_verify_nonce( null );
if ( isset( $_GET['p24'] ) && isset( $_GET['subscription_get'] ) ) {
if ( isset( $_GET['user'] ) ) {
$for_user = (int) $_GET['user'];
} else {
$for_user = null;
}
if ( isset( $_GET['subscription'] ) ) {
$subscription = (int) $_GET['subscription'];
} else {
$subscription = null;
}
header( 'Content-Type: application/json' );
$list = self::query_db( $for_user, $subscription );
echo wp_json_encode( $list );
exit();
}
}
/**
* Bind events.
*/
public function bind_core_events() {
add_action( 'admin_init', array( $this, 'try_serve' ) );
}
}

View File

@@ -0,0 +1,144 @@
<?php
/**
* File that define P24_Subscription_Config class.
*
* @package Przelewy24
*/
defined( 'ABSPATH' ) || exit;
/**
* Class P24_Subscription_Config
*/
class P24_Subscription_Config {
/**
* Days to renew.
*
* @return int
*/
public static function days_to_renew() {
$ret = get_option( 'przelewy24_subscriptions_days' );
if ( ! isset( $ret ) ) {
return 1;
} else {
return (int) $ret;
}
}
/**
* Is active.
*
* @return bool
*/
public static function is_active() {
$ret = get_option( 'przelewy24_subscriptions_active' );
if ( ! isset( $ret ) ) {
return false;
} else {
return 'yes' === $ret;
}
}
/**
* Get page id.
*
* @return int|null
*/
public static function page_id() {
$page_id = (int) get_option( 'p24_subscription_page_id', 0 );
return $page_id ? $page_id : null;
}
/**
* Set page id.
*
* @param int|null $page_id Id of page, null to unset.
*/
public static function set_page_id( $page_id ) {
$page_id = (int) $page_id;
$page_id = $page_id ? $page_id : null;
update_option( 'p24_subscription_page_id', $page_id );
}
/**
* Set page for user.
*/
public static function set_page() {
$page_id = self::page_id();
if ( $page_id ) {
$subscription_page = get_post( $page_id );
if ( ! $subscription_page ) {
$page_id = null;
}
}
if ( ! $page_id ) {
$page_id = wp_insert_post(
array(
'post_title' => 'P24 Subskrypcje',
'post_name' => 'p24-subscription',
'post_type' => 'page',
'post_content' => '<!-- wp:shortcode -->[p24_user_subscription]<!-- /wp:shortcode -->',
'post_status' => 'publish',
)
);
self::set_page_id( $page_id );
}
return $page_id;
}
/**
* Update page.
*
* @param string $action Name of action.
*/
private static function update_page( $action ) {
switch ( $action ) {
case 'delete':
self::set_page_id( null );
break;
case 'force':
self::set_page_id( null );
self::set_page();
break;
case 'generate':
self::set_page();
break;
case 'nothing':
default:
break;
}
}
/**
* Update config.
*
* @param array $data Provided data.
* @return array
*/
public static function update_config( $data ) {
if ( array_key_exists( 'p24_subscriptions_active', $data ) ) {
$active = (bool) $data['p24_subscriptions_active'];
} else {
$active = false;
}
if ( array_key_exists( 'p24_subscriptions_days', $data ) ) {
$days = (int) $data['p24_subscriptions_days'];
}
if ( ! isset( $days ) || $days < 1 ) {
$days = 1;
}
if ( array_key_exists( 'p24_subscription_page', $data ) ) {
self::update_page( $data['p24_subscription_page'] );
}
$ret = array(
'przelewy24_subscriptions_active' => $active ? 'yes' : 'no',
'przelewy24_subscriptions_days' => $days,
);
return $ret;
}
}

View File

@@ -0,0 +1,370 @@
<?php
/**
* File that define P24_Subscription_Db class.
*
* @package Przelewy24
*/
defined( 'ABSPATH' ) || exit;
/**
* Class P24_Subscription_Db
*/
class P24_Subscription_Db {
/**
* Extend or add subscription.
*
* @param P24_No_Mc_Product_Subscription $subscription Subcription product.
* @param int $quantity Quantity of subscriptions.
* @param WP_User $user Buyer.
* @param WC_Order $order Current order.
*/
public static function extend_subscription( $subscription, $quantity, $user, $order ) {
global $wpdb;
$user_id = (int) $user->ID;
$subscription_id = (int) $subscription->get_id();
/* We need a plain integer for database relations. */
$order_id = (int) $order->get_id();
$data = $wpdb->get_row(
$wpdb->prepare(
"SELECT id, valid_to FROM {$wpdb->prefix}woocommerce_p24_subscription WHERE user_id = %d AND product_id = %d;",
array( $user_id, $subscription_id )
)
); /* db call ok; no cache ok */
$now = new DateTime();
$days = (int) ( $subscription->get_days() * $quantity );
if ( $data ) {
$id = (int) $data->id;
$alt_date = new DateTime( "$days days" );
try {
$date = new DateTime( $data->valid_to );
$date->modify( "$days days" );
/* If the subscription is too old. */
if ( $date < $alt_date ) {
$date = $alt_date;
}
} catch ( Exception $ex ) {
/* The best fall back we can do. */
$date = $alt_date;
}
$wpdb->update(
"{$wpdb->prefix}woocommerce_p24_subscription",
array(
'valid_to' => $date->format( 'Y-m-d H:i:s' ),
'last_order_id' => $order_id,
'last_checked' => $now->format( 'Y-m-d H:i:s' ),
),
array( 'id' => $id ), /* The NULL is not SQL compatible. */
array( '%s', '%d', '%s' ),
array( '%d' )
); /* db call ok; no cache ok */
} else {
$date = new DateTime( "$days days" );
$data = array(
'user_id' => $user_id,
'product_id' => $subscription_id,
'valid_to' => $date->format( 'Y-m-d H:i:s' ),
'extend' => 0,
'last_order_id' => $order_id,
'last_checked' => $now->format( 'Y-m-d H:i:s' ),
);
$formats = array( '%d', '%d', '%s', '%d', '%d', '%s' );
$wpdb->insert( "{$wpdb->prefix}woocommerce_p24_subscription", $data, $formats ); /* db call ok */
}
}
/**
* Add card reference.
*
* @param WC_Order $order Order.
* @param string $card_ref Card reference.
*/
public static function add_card_reference( $order, $card_ref ) {
global $wpdb;
/* We need a plain integer for database relations. */
$last_order_id = (int) $order->get_id();
$now = new DateTime();
$wpdb->update(
"{$wpdb->prefix}woocommerce_p24_subscription",
array(
'extend' => 1,
'card_ref' => $card_ref,
'last_checked' => $now->format( 'Y-m-d H:i:s' ),
),
array( 'last_order_id' => $last_order_id ), /* The NULL is not SQL compatible. */
array( '%d', '%s', '%s' ),
array( '%d' )
); /* db call ok; no cache ok */
}
/**
* Update card reference.
*
* @param int $subcription_id Subcription id.
* @param string $card_ref Card reference.
*/
public static function update_card_reference( $subcription_id, $card_ref ) {
global $wpdb;
$now = new DateTime();
$wpdb->update(
"{$wpdb->prefix}woocommerce_p24_subscription",
array(
'extend' => 1,
'card_ref' => $card_ref,
'last_checked' => $now->format( 'Y-m-d H:i:s' ),
),
array( 'id' => (int) $subcription_id ), /* The NULL is not SQL compatible. */
array( '%d', '%s', '%s' ),
array( '%d' )
); /* db call ok; no cache ok */
}
/**
* Clear card reference.
*
* @param int $subcription_id Subcription id.
*/
public static function clear_card_reference( $subcription_id ) {
global $wpdb;
$wpdb->update(
"{$wpdb->prefix}woocommerce_p24_subscription",
array(
'extend' => 0,
'card_ref' => null,
),
array( 'id' => (int) $subcription_id ), /* The NULL is not SQL compatible. */
array( '%d', '%s' ),
array( '%d' )
); /* db call ok; no cache ok */
}
/**
* End subscription.
*
* @param int $subscription_id Subscription id.
* @return bool True on success.
*/
public static function end_subscription( $subscription_id ) {
global $wpdb;
$yesterday = new DateTime( 'yesterday' );
$ok = $wpdb->update(
"{$wpdb->prefix}woocommerce_p24_subscription",
array(
'extend' => 0,
'card_ref' => null,
'valid_to' => $yesterday->format( 'Y-m-d H:i:s' ),
),
array( 'id' => (int) $subscription_id ), /* The NULL is not SQL compatible. */
array( '%d', '%s', '%s' ),
array( '%d' )
); /* db call ok; no cache ok */
return (bool) $ok;
}
/**
* Get active list.
*
* @return array|object|null
*/
public static function get_active_list() {
global $wpdb;
$now = new DateTime();
$list = $wpdb->get_results(
$wpdb->prepare(
"
SELECT
u.user_nicename,
u.user_email,
s.valid_to,
p.post_title AS subscription_title,
s.id AS record_id
FROM {$wpdb->prefix}woocommerce_p24_subscription AS s
INNER JOIN {$wpdb->prefix}posts AS p ON p.ID = s.product_id
INNER JOIN {$wpdb->prefix}users AS u ON u.ID = s.user_id
WHERE s.valid_to > %s
ORDER BY p.post_title, u.user_email, s.id
;
",
array( $now->format( 'Y-m-d H:i:s' ) )
)
); /* db call ok; no cache ok */
return $list;
}
/**
* Get inactive list.
*
* @return array|object|null
*/
public static function get_inactive_list() {
global $wpdb;
$now = new DateTime();
$list = $wpdb->get_results(
$wpdb->prepare(
"
SELECT
u.user_nicename,
u.user_email,
s.valid_to,
p.post_title AS subscription_title
FROM {$wpdb->prefix}woocommerce_p24_subscription AS s
INNER JOIN {$wpdb->prefix}posts AS p ON p.ID = s.product_id
INNER JOIN {$wpdb->prefix}users AS u ON u.ID = s.user_id
WHERE s.valid_to < %s
ORDER BY p.post_title, u.user_email, s.id
;
",
array( $now->format( 'Y-m-d H:i:s' ) )
)
); /* db call ok; no cache ok */
return $list;
}
/**
* Get active list for user.
*
* @return array|object|null
* @param WP_User $user User of interest.
*/
public static function get_active_list_for_user( $user ) {
global $wpdb;
$user_id = $user->ID;
$now = new DateTime();
$list = $wpdb->get_results(
$wpdb->prepare(
"
SELECT
s.id AS record_id,
s.valid_to,
s.card_ref,
p.ID AS product_id,
p.post_title AS subscription_title
FROM {$wpdb->prefix}woocommerce_p24_subscription AS s
INNER JOIN {$wpdb->prefix}posts AS p ON p.ID = s.product_id
WHERE s.valid_to > %s
AND s.user_id = %d
ORDER BY p.post_title, s.id
;
",
array( $now->format( 'Y-m-d H:i:s' ), $user_id )
)
); /* db call ok; no cache ok */
return $list;
}
/**
* Get inactive list for user.
*
* @return array|object|null
* @param WP_User $user User of interest.
*/
public static function get_inactive_list_for_user( $user ) {
global $wpdb;
$user_id = $user->ID;
$now = new DateTime();
$list = $wpdb->get_results(
$wpdb->prepare(
"
SELECT
s.id AS record_id,
p.ID AS product_id,
p.post_title AS subscription_title
FROM {$wpdb->prefix}woocommerce_p24_subscription AS s
INNER JOIN {$wpdb->prefix}posts AS p ON p.ID = s.product_id
WHERE s.valid_to < %s
AND s.user_id = %d
ORDER BY p.post_title, s.id
;
",
array( $now->format( 'Y-m-d H:i:s' ), $user_id )
)
); /* db call ok; no cache ok */
return $list;
}
/**
* Mark checked.
*
* @param int $id Id of subscription.
*/
public static function mark_checked( $id ) {
global $wpdb;
$id = (int) $id;
$now = new DateTime();
$wpdb->update(
"{$wpdb->prefix}woocommerce_p24_subscription",
array(
'last_checked' => $now->format( 'Y-m-d H:i:s' ),
),
array( 'id' => $id ), /* The NULL is not SQL compatible. */
array( '%s' ),
array( '%d' )
); /* db call ok; no cache ok */
}
/**
* Find_subscription_to_extends.
*
* @param DateTimeInterface $critical_date The date of subscription.
*/
public static function find_subscription_to_extends( $critical_date ) {
global $wpdb;
$critical_date_string = $critical_date->format( 'Y-m-d H:i:s' );
$cool_down = new DateTime( '- 1 hour' );
$cool_down_string = $cool_down->format( 'Y-m-d H:i:s' );
$data = $wpdb->get_results(
$wpdb->prepare(
"
SELECT id, product_id, user_id, last_order_id, card_ref
FROM {$wpdb->prefix}woocommerce_p24_subscription
WHERE valid_to < %s AND extend <> 0 AND card_ref IS NOT NULL AND last_checked < %s
;
",
array( $critical_date_string, $cool_down_string )
)
); /* db call ok; no cache ok */
return $data;
}
/**
* Get extended data for single record.
*
* @param int $subscription_id Subsription id.
* @return array|null
*/
public static function get_extended_data_for_single( $subscription_id ) {
$subscription_id = (int) $subscription_id;
global $wpdb;
$data = $wpdb->get_results(
$wpdb->prepare(
"
SELECT
u.user_nicename,
u.user_email,
p.post_title AS subscription_title
FROM {$wpdb->prefix}woocommerce_p24_subscription AS s
INNER JOIN {$wpdb->prefix}posts AS p ON p.ID = s.product_id
INNER JOIN {$wpdb->prefix}users AS u ON u.ID = s.user_id
WHERE s.id = %d
;
",
array( $subscription_id )
)
); /* db call ok; no cache ok */
if ( $data ) {
return (array) reset( $data );
} else {
return null;
}
}
}

View File

@@ -0,0 +1,218 @@
<?php
/**
* File that define P24_Subscription_User class.
*
* @package Przelewy24
*/
defined( 'ABSPATH' ) || exit;
/**
* Class P24_Subscription_User
*/
class P24_Subscription_User {
/**
* The P24_Core instance.
*
* @var P24_Core
*/
private $plugin_core;
/**
* The constructor.
*
* @param P24_Core $plugin_core The P24_Core instance.
*/
public function __construct( P24_Core $plugin_core ) {
$this->plugin_core = $plugin_core;
}
/**
* Extend nav.
*
* @param array $endpoints Default endpoints.
* @param array $descriptions Additional endpoints description.
* @return array
*/
public function extend_nav( $endpoints, $descriptions ) {
$endpoints['p24-subscriptions-user'] = __( 'Subskrypcje P24' );
return $endpoints;
}
/**
* Set nav url.
*
* @param string $url Proposed url.
* @param string $endpoint Endpoint name.
* @param string $value Unused in our context.
* @param string $permalink Unused in our context.
* @return string
*/
public function set_nav_url( $url, $endpoint, $value, $permalink ) {
if ( 'p24-subscriptions-user' === $endpoint ) {
$post = get_post( P24_Subscription_Config::page_id() );
if ( $post ) {
$url = get_post_permalink( $post );
}
}
return $url;
}
/**
* Get post data.
*
* There are problems with arrays in $_POST. This is workaround.
*/
private function get_post() {
/* We are forced to verify nonce in this place. */
if ( isset( $_POST['p24_nonce'] ) ) {
$nonce = sanitize_key( $_POST['p24_nonce'] );
if ( ! wp_verify_nonce( $nonce, 'p24_action' ) ) {
return array();
}
}
return $_POST;
}
/**
* Process form.
*
* @param WP_User $user The active user.
* @param array $cards The user cards.
*/
private function process_form( $user, $cards ) {
$valid_keys = array_map(
function ( $card ) {
return $card->custom_key;
},
$cards
);
$post = $this->get_post();
if ( ! $post ) {
return;
}
if ( ! array_key_exists( 'p24_action_type_field', $post ) ) {
return;
} elseif ( 'user_subscriptions' !== $post['p24_action_type_field'] ) {
return;
} elseif ( ! array_key_exists( 'card_for_subscription', $post ) ) {
return;
}
$cards_for_subscription = wp_unslash( $post['card_for_subscription'] );
foreach ( $cards_for_subscription as $subscription_id => $card_ref ) {
if ( in_array( $card_ref, $valid_keys, true ) ) {
P24_Subscription_Db::update_card_reference( (int) $subscription_id, $card_ref );
} else {
P24_Subscription_Db::clear_card_reference( (int) $subscription_id );
}
}
}
/**
* Render.
*/
public function render() {
$user = wp_get_current_user();
if ( $user->ID ) {
$cards = WC_Gateway_Przelewy24::get_all_cards( (int) $user->ID );
$this->process_form( $user, $cards );
$subscriptions = P24_Subscription_Db::get_active_list_for_user( $user );
$files = $this->get_all_files_for_user( $user );
$inactive = P24_Subscription_Db::get_inactive_list_for_user( $user );
} else {
$cards = array();
$subscriptions = array();
$files = array();
$inactive = array();
}
$data = compact( 'user', 'subscriptions', 'cards', 'files', 'inactive' );
$this->plugin_core->render_template( 'subscriptions-user', $data );
}
/**
* Find file.
*
* @param WP_User $user Use of interest.
* @param int $subscription_id Subscription id.
* @param string $file_name File name.
* @return array|null
*/
private function find_file( $user, $subscription_id, $file_name ) {
$subscription_id = (int) $subscription_id;
$file_name = (string) $file_name;
$subscriptions = P24_Subscription_Db::get_active_list_for_user( $user );
foreach ( $subscriptions as $subscription ) {
if ( (int) $subscription->record_id === $subscription_id ) {
$files = P24_Subscription::files_for_subscription( $subscription->product_id );
foreach ( $files as $file ) {
if ( $file['name'] === $file_name ) {
return $file;
}
}
return null;
}
}
return null;
}
/**
* Get all files for user.
*
* @param WP_User $user Use of interest.
* @return array
*/
private function get_all_files_for_user( $user ) {
$all_files = array();
$subscriptions = P24_Subscription_Db::get_active_list_for_user( $user );
foreach ( $subscriptions as $subscription ) {
$files = P24_Subscription::files_for_subscription( $subscription->product_id );
array_walk(
$files,
function ( &$record ) use ( $subscription ) {
$record['parent_id'] = $subscription->record_id;
$record['name_url'] = rawurlencode( $record['name'] );
}
);
$all_files = array_merge( $all_files, $files );
}
return $all_files;
}
/**
* Try download.
*
* @throws LogicException The callee should finish script.
*/
public function try_download() {
global $current_user;
if ( ! $current_user || ! $current_user->ID ) {
return;
}
wp_verify_nonce( null );
if ( isset( $_GET['subscription_id'] ) && isset( $_GET['file_name'] ) && isset( $_GET['p24'] ) && isset( $_GET['download'] ) ) {
$subscription_id = sanitize_text_field( wp_unslash( $_GET['subscription_id'] ) );
$file_name = sanitize_text_field( wp_unslash( $_GET['file_name'] ) );
$file = $this->find_file( $current_user, $subscription_id, $file_name );
if ( $file ) {
WC_Download_Handler::download_file_xsendfile( $file['url'], $file['name'] );
exit();
}
}
}
/**
* Bind events.
*/
public function bind_core_events() {
add_filter( 'woocommerce_account_menu_items', array( $this, 'extend_nav' ), 10, 2 );
add_filter( 'woocommerce_get_endpoint_url', array( $this, 'set_nav_url' ), 10, 4 );
add_action( 'init', array( $this, 'try_download' ) );
add_shortcode( 'p24_user_subscription', array( $this, 'render' ) );
}
}

View File

@@ -0,0 +1,336 @@
<?php
/**
* File that define P24_Subscription class.
*
* @package Przelewy24
*/
defined( 'ABSPATH' ) || exit;
/**
* Class P24_Subscription
*/
class P24_Subscription {
/**
* The P24_Core instance.
*
* @var P24_Core
*/
private $plugin_core;
/**
* The P24_Core instance.
*
* @var P24_Subscription_User
*/
private $for_user;
/**
* The P24_Core instance.
*
* @var P24_Subscription_Admin
*/
private $for_admin;
/**
* The P24_Subscription_Api instance.
*
* @var P24_Subscription_Api
*/
private $api;
/**
* The constructor.
*
* @param P24_Core $plugin_core The P24_Core instance.
*/
public function __construct( P24_Core $plugin_core ) {
$this->plugin_core = $plugin_core;
$this->for_user = new P24_Subscription_User( $plugin_core );
$this->for_admin = new P24_Subscription_Admin( $plugin_core );
$this->api = new P24_Subscription_Api();
}
/**
* Register subcription product type
*
* @param array $types Provided types.
* @return array Extended types.
*/
public function register_product_type( $types ) {
$types[ P24_No_Mc_Product_Subscription::TYPE ] = __( 'Subskrypcja P24' );
return $types;
}
/**
* Detect subcription product class.
*
* @param string $classname Default classname.
* @param string $product_type Product type.
* @return string
*/
public function subscription_class_detector( $classname, $product_type ) {
if ( P24_No_Mc_Product_Subscription::TYPE === $product_type ) {
$classname = P24_No_Mc_Product_Subscription::class;
}
return $classname;
}
/**
* Render subscription panel.
*/
public function render_subscription_panel() {
global $post;
$post_id = (int) $post->ID;
$data = array(
'files' => self::files_for_subscription( $post_id ),
);
$this->plugin_core->render_template( 'subscriptions-product', $data );
}
/**
* Save subscription fields.
*
* @param int $post_id Id of post.
* @param WP_Post $post The post itself.
*/
public function save_subscription_fields( $post_id, $post ) {
if ( isset( $_POST['_wpnonce'] ) ) {
wp_verify_nonce( sanitize_textarea_field( wp_unslash( $_POST['_wpnonce'] ) ), 'update-post_' . $post->ID );
}
if ( isset( $_POST['product-type'] ) ) {
$product_type = sanitize_text_field( wp_unslash( $_POST['product-type'] ) );
if ( P24_No_Mc_Product_Subscription::TYPE !== $product_type ) {
/* Different product type, nothing sane to do. */
return;
}
}
if ( isset( $_POST['_subscription_price'] ) ) {
/* Update two metas with the same value. For better compatibility. */
$price = sanitize_text_field( wp_unslash( $_POST['_subscription_price'] ) );
update_post_meta( $post_id, '_subscription_price', $price );
update_post_meta( $post_id, '_price', $price );
}
/* The WordPress standards allow only the simplest for lops. */
$i = 0;
$files_to_save = array();
while ( array_key_exists( $i, $_POST['_p24_sub_file_urls'] ) ) {
$url = sanitize_text_field( wp_unslash( $_POST['_p24_sub_file_urls'][ $i ] ) );
$name = 'file_' . $i;
if ( array_key_exists( $i, $_POST['_p24_sub_file_names'] ) ) {
$provided_name = sanitize_text_field( wp_unslash( $_POST['_p24_sub_file_names'][ $i ] ) );
if ( '' !== $provided_name ) {
$name = $provided_name;
}
}
$files_to_save[] = compact( 'name', 'url' );
++$i;
}
update_post_meta( $post_id, 'p24_sub_files', $files_to_save );
if ( isset( $_POST['_days'] ) ) {
$days = (int) sanitize_text_field( wp_unslash( $_POST['_days'] ) );
if ( $days < 1 ) {
$days = 1;
}
update_post_meta( $post_id, '_days', $days );
}
}
/**
* Output the simple product add to cart area.
*/
public function render_subscription_buy_form() {
$nonce_action = 'p24_add_subscription';
if ( isset( $_POST['_wpnonce'] ) ) {
wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), $nonce_action );
$post_data = $_POST;
} else {
$post_data = array();
}
$data = compact( 'post_data', 'nonce_action' );
$this->plugin_core->render_template( 'add-subscription-to-cart', $data );
}
/**
* Check for subscriptions.
*
* This code should execute only if order is paid and saved.
*
* @param int $order_id The id of existing order.
* @throws LogicException If the function is misused.
*/
public function check_for_subscriptions_in_order( $order_id ) {
$order_id = (int) $order_id;
if ( ! $order_id ) {
throw new LogicException( 'Order should be present before call to this function.' );
}
$order = new WC_Order( $order_id );
if ( ! $order->is_paid() ) {
throw new LogicException( 'Order should be paid before call to this function.' );
}
$user = $order->get_user();
if ( ! $user ) {
/* If there is no user, the subscription cannot be created. */
return;
}
$items = $order->get_items();
foreach ( $items as $item ) {
if ( ! $item instanceof WC_Order_Item_Product ) {
continue;
}
$subscription = $item->get_product();
if ( $subscription instanceof P24_No_Mc_Product_Subscription ) {
$quantity = (int) $item->get_quantity();
P24_Subscription_Db::extend_subscription( $subscription, $quantity, $user, $order );
}
}
}
/**
* Add_card_ref.
*
* @param WC_Order $order Order.
* @param string|null $cart_ref Kay of card, it is not reference id for Przelewy24.
*/
public function add_card_ref( $order, $cart_ref ) {
if ( $cart_ref ) {
P24_Subscription_Db::add_card_reference( $order, $cart_ref );
}
}
/**
* Charge_card.
*
* @param WC_Order $order Order to pay.
* @param string $card_ref Kay of card, it is not reference id for Przelewy24.
* @return bool
*/
private function charge_card( $order, $card_ref ) {
$data = P24_Sub_Generator::generate_payload_for_rest( $order );
if ( ! $data ) {
return false;
}
$card = P24_Sub_Generator::find_saved_card( $card_ref, $order->get_user_id() );
if ( ! $card ) {
return false;
}
$config_accessor = P24_Settings_Helper::load_settings( $order->get_currency() );
$data['regulationAccept'] = true;
$rest_transaction = new P24_Rest_Transaction( $config_accessor );
$data['methodRefId'] = $card['ref'];
$transaction_info = $rest_transaction->register( $data );
$token = $transaction_info['data']['token'];
if ( ! $token ) {
return false;
}
$rest_card = new P24_Rest_Card( $config_accessor );
$payment_info = $rest_card->chargeWithout3ds( $token );
if ( isset( $payment_info['data']['orderId'] ) ) {
$order_id = $payment_info['data']['orderId'];
$order->update_meta_data( P24_Core::ORDER_P24_ID, $order_id );
$order->save_meta_data();
}
return true;
}
/**
* Create subscription.
*
* @param int $product_id Product id.
* @param int $user_id User id.
* @param int $last_order_id Last order id.
* @param string $card_ref Kay of card, it is not reference id for Przelewy24.
*
* @throws LogicException This error is not expected.
*/
private function create_subscription( $product_id, $user_id, $last_order_id, $card_ref ) {
$user_id = (int) $user_id;
$product_id = (int) $product_id;
$product = wc_get_product( $product_id );
$last_order = wc_get_order( $last_order_id );
$order = wc_create_order();
$order->add_product( $product );
$order->set_address( $last_order->get_address( 'billing' ), 'billing' );
try {
$order->set_currency( $last_order->get_currency() );
$order->set_customer_id( $user_id );
} catch ( WC_Data_Exception $ex ) {
$msg = 'The function shuld not be called if conditions above cannot be satisfied.';
throw new LogicException( $msg, 0, $ex );
}
$order->calculate_totals();
$this->charge_card( $order, $card_ref );
}
/**
* Files_for_subscription.
*
* @param int $subscription_id Subscription id.
* @return array
*/
public static function files_for_subscription( $subscription_id ) {
$subscription_id = (int) $subscription_id;
$files = get_post_meta( $subscription_id, 'p24_sub_files', true );
if ( $files ) {
return $files;
} else {
return array();
}
}
/**
* Check subscription to extend.
*/
public function check_subscription_to_extend() {
$critical_date = new DateTime( P24_Subscription_Config::days_to_renew() . ' days' );
$todo = P24_Subscription_Db::find_subscription_to_extends( $critical_date );
$one = array_shift( $todo );
if ( $one ) {
$this->create_subscription( $one->product_id, $one->user_id, $one->last_order_id, $one->card_ref );
P24_Subscription_Db::mark_checked( $one->id );
}
if ( $todo ) {
wp_schedule_single_event( time() + 60, 'p24_extra_do_subscription' );
}
}
/**
* Bind events.
*/
public function bind_core_events() {
if ( ! P24_Subscription_Config::is_active() ) {
/* Do not bind any events. */
return;
}
add_filter( 'product_type_selector', array( $this, 'register_product_type' ) );
add_filter( 'woocommerce_product_class', array( $this, 'subscription_class_detector' ), 10, 2 );
add_action( 'woocommerce_product_data_panels', array( $this, 'render_subscription_panel' ) );
add_action( 'woocommerce_process_product_meta', array( $this, 'save_subscription_fields' ), 20, 2 );
add_action( 'woocommerce_p24_subscription_add_to_cart', array( $this, 'render_subscription_buy_form' ), 30 );
add_action( 'woocommerce_payment_complete', array( $this, 'check_for_subscriptions_in_order' ), 10, 1 );
add_action( 'p24_payment_complete', array( $this, 'add_card_ref' ), 10, 2 );
add_action( 'p24_daily_event', array( $this, 'check_subscription_to_extend' ) );
add_action( 'p24_extra_do_subscription', array( $this, 'check_subscription_to_extend' ) );
$this->for_user->bind_core_events();
$this->for_admin->bind_core_events();
$this->api->bind_core_events();
}
}