556 lines
14 KiB
PHP
556 lines
14 KiB
PHP
|
<?php
|
||
|
/**
|
||
|
* Install Function
|
||
|
*
|
||
|
* @package EDD
|
||
|
* @subpackage Functions/Install
|
||
|
* @copyright Copyright (c) 2018, Easy Digital Downloads, LLC
|
||
|
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
|
||
|
* @since 1.0
|
||
|
*/
|
||
|
|
||
|
// Exit if accessed directly
|
||
|
defined( 'ABSPATH' ) || exit;
|
||
|
|
||
|
/**
|
||
|
* Get the current database version
|
||
|
*
|
||
|
* @since 3.0
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
function edd_get_db_version() {
|
||
|
$db_version = get_option( 'edd_version' );
|
||
|
$retval = ! empty( $db_version )
|
||
|
? edd_format_db_version( $db_version )
|
||
|
: false;
|
||
|
|
||
|
return $retval;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update the EDD version in the options table
|
||
|
*
|
||
|
* @since 3.0
|
||
|
*/
|
||
|
function edd_update_db_version() {
|
||
|
if ( defined( 'EDD_VERSION' ) ) {
|
||
|
update_option( 'edd_version', edd_format_db_version( EDD_VERSION ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Format the EDD version (going into or coming from the database.)
|
||
|
*
|
||
|
* @since 3.0
|
||
|
*
|
||
|
* @param string $version
|
||
|
* @return string
|
||
|
*/
|
||
|
function edd_format_db_version( $version = '' ) {
|
||
|
return preg_replace( '/[^0-9.].*/', '', $version );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check if the upgrade routine has been run for a specific action
|
||
|
*
|
||
|
* @since 2.3
|
||
|
* @param string $upgrade_action The upgrade action to check completion for
|
||
|
* @return bool If the action has been added to the copmleted actions array
|
||
|
*/
|
||
|
function edd_has_upgrade_completed( $upgrade_action = '' ) {
|
||
|
|
||
|
// Bail if no upgrade action to check
|
||
|
if ( empty( $upgrade_action ) ) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// Get completed upgrades
|
||
|
$completed_upgrades = edd_get_completed_upgrades();
|
||
|
|
||
|
// Return true if in array, false if not
|
||
|
return in_array( $upgrade_action, $completed_upgrades, true );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get's the array of completed upgrade actions
|
||
|
*
|
||
|
* @since 2.3
|
||
|
* @return array The array of completed upgrades
|
||
|
*/
|
||
|
function edd_get_completed_upgrades() {
|
||
|
|
||
|
// Get the completed upgrades for this site
|
||
|
$completed_upgrades = get_option( 'edd_completed_upgrades', array() );
|
||
|
|
||
|
// Return array of completed upgrades
|
||
|
return (array) $completed_upgrades;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Install
|
||
|
*
|
||
|
* Runs on plugin install by setting up the post types, custom taxonomies,
|
||
|
* flushing rewrite rules to initiate the new 'downloads' slug and also
|
||
|
* creates the plugin and populates the settings fields for those plugin
|
||
|
* pages.
|
||
|
*
|
||
|
* @since 1.0
|
||
|
* @param bool $network_wide If the plugin is being network-activated
|
||
|
* @return void
|
||
|
*/
|
||
|
function edd_install( $network_wide = false ) {
|
||
|
|
||
|
// Multi-site install
|
||
|
if ( is_multisite() && ! empty( $network_wide ) ) {
|
||
|
edd_run_multisite_install();
|
||
|
|
||
|
// Single site install
|
||
|
} else {
|
||
|
edd_run_install();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Run the EDD installation on every site in the current network.
|
||
|
*
|
||
|
* @since 3.0
|
||
|
*/
|
||
|
function edd_run_multisite_install() {
|
||
|
global $wpdb;
|
||
|
|
||
|
// Get site count
|
||
|
$network_id = get_current_network_id();
|
||
|
$query = $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->blogs} WHERE site_id = %d", $network_id );
|
||
|
$count = $wpdb->get_var( $query );
|
||
|
|
||
|
// Bail if no sites (this is really strange and bad)
|
||
|
if ( empty( $count ) || is_wp_error( $count ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Setup the steps
|
||
|
$per_step = 100;
|
||
|
$total_steps = ceil( $count / $per_step );
|
||
|
$step = 1;
|
||
|
$offset = 0;
|
||
|
|
||
|
// Step through all sites in this network in groups of 100
|
||
|
do {
|
||
|
|
||
|
// Get next batch of site IDs
|
||
|
$query = $wpdb->prepare( "SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = %d LIMIT %d, %d", $network_id, $offset, $per_step );
|
||
|
$site_ids = $wpdb->get_col( $query );
|
||
|
|
||
|
// Proceed if site IDs exist
|
||
|
if ( ! empty( $site_ids ) ) {
|
||
|
foreach ( $site_ids as $site_id ) {
|
||
|
edd_run_install( $site_id );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Bump the limit for the next iteration
|
||
|
$offset = ( $step * $per_step ) - 1;
|
||
|
|
||
|
// Bump the step
|
||
|
++$step;
|
||
|
|
||
|
// Bail when steps are greater than or equal to total steps
|
||
|
} while ( $total_steps > $step );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Run the EDD Install process
|
||
|
*
|
||
|
* @since 2.5
|
||
|
* @since 3.0 Added $site_id parameter
|
||
|
*/
|
||
|
function edd_run_install( $site_id = false ) {
|
||
|
|
||
|
// Not switched
|
||
|
$switched = false;
|
||
|
|
||
|
// Maybe switch to a site
|
||
|
if ( ! empty( $site_id ) ) {
|
||
|
switch_to_blog( $site_id );
|
||
|
$switched = true;
|
||
|
}
|
||
|
|
||
|
// Get the current database version
|
||
|
$current_version = edd_get_db_version();
|
||
|
|
||
|
// Setup the components (customers, discounts, logs, etc...)
|
||
|
edd_setup_components();
|
||
|
|
||
|
// Setup the Downloads Custom Post Type
|
||
|
edd_setup_edd_post_types();
|
||
|
|
||
|
// Setup the Download Taxonomies
|
||
|
edd_setup_download_taxonomies();
|
||
|
|
||
|
// Clear the permalinks
|
||
|
flush_rewrite_rules( false );
|
||
|
|
||
|
// Install the default pages
|
||
|
edd_install_pages();
|
||
|
|
||
|
// Maybe save the previous version, only if different than current
|
||
|
if ( ! empty( $current_version ) && ( edd_format_db_version( EDD_VERSION ) !== $current_version ) ) {
|
||
|
if ( version_compare( $current_version, edd_format_db_version( EDD_VERSION ), '>' ) ) {
|
||
|
$downgraded = true;
|
||
|
update_option( 'edd_version_downgraded_from', $current_version );
|
||
|
}
|
||
|
|
||
|
update_option( 'edd_version_upgraded_from', $current_version );
|
||
|
}
|
||
|
|
||
|
// Install the default settings
|
||
|
edd_install_settings();
|
||
|
|
||
|
// Set the activation date.
|
||
|
edd_get_activation_date();
|
||
|
|
||
|
// Create wp-content/uploads/edd/ folder and the .htaccess file
|
||
|
if ( ! function_exists( 'edd_create_protection_files' ) ) {
|
||
|
require_once EDD_PLUGIN_DIR . 'includes/admin/upload-functions.php';
|
||
|
}
|
||
|
if ( function_exists( 'edd_create_protection_files' ) ) {
|
||
|
edd_create_protection_files( true );
|
||
|
}
|
||
|
|
||
|
// Create custom tables. (@todo move to BerlinDB)
|
||
|
EDD()->notifications->create_table();
|
||
|
|
||
|
// Create EDD shop roles
|
||
|
$roles = new EDD_Roles;
|
||
|
$roles->add_roles();
|
||
|
$roles->add_caps();
|
||
|
|
||
|
// API version
|
||
|
$api = new EDD_API;
|
||
|
update_option( 'edd_default_api_version', 'v' . $api->get_version() );
|
||
|
|
||
|
// Check for PHP Session support, and enable if available
|
||
|
EDD()->session->use_php_sessions();
|
||
|
|
||
|
// Maybe set all upgrades as complete (only on fresh installation)
|
||
|
edd_set_all_upgrades_complete();
|
||
|
|
||
|
// Update the database version (must be at end, but before site restore)
|
||
|
edd_update_db_version();
|
||
|
|
||
|
// Maybe switch back
|
||
|
if ( true === $switched ) {
|
||
|
restore_current_blog();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Maybe set upgrades as complete during a fresh
|
||
|
* @since 3.0
|
||
|
*/
|
||
|
function edd_set_all_upgrades_complete() {
|
||
|
|
||
|
// Bail if not a fresh installation
|
||
|
if ( edd_get_db_version() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Maybe include an admin-area only file/function
|
||
|
if ( ! function_exists( 'edd_set_upgrade_complete' ) ) {
|
||
|
require_once EDD_PLUGIN_DIR . 'includes/admin/upgrades/upgrade-functions.php';
|
||
|
}
|
||
|
|
||
|
// When new upgrade routines are added, mark them as complete on fresh install
|
||
|
$upgrade_routines = array(
|
||
|
'upgrade_payment_taxes',
|
||
|
'upgrade_customer_payments_association',
|
||
|
'upgrade_user_api_keys',
|
||
|
'remove_refunded_sale_logs',
|
||
|
'update_file_download_log_data',
|
||
|
);
|
||
|
$edd_30_upgrades = edd_get_v30_upgrades();
|
||
|
$upgrade_routines = array_merge( $upgrade_routines, array_keys( $edd_30_upgrades ) );
|
||
|
|
||
|
// Loop through upgrade routines and mark them as complete
|
||
|
foreach ( $upgrade_routines as $upgrade ) {
|
||
|
edd_set_upgrade_complete( $upgrade );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Install the required pages
|
||
|
*
|
||
|
* @since 3.0
|
||
|
*/
|
||
|
function edd_install_pages() {
|
||
|
|
||
|
// Get all of the EDD settings
|
||
|
$current_options = get_option( 'edd_settings', array() );
|
||
|
|
||
|
// Required store pages
|
||
|
$pages = edd_get_required_pages();
|
||
|
|
||
|
// Look for missing pages
|
||
|
$missing_pages = array_diff_key( $pages, $current_options );
|
||
|
$pages_to_check = array_intersect_key( $current_options, $pages );
|
||
|
|
||
|
// Query for any existing pages
|
||
|
$posts = new WP_Query(
|
||
|
array(
|
||
|
'include' => array_values( $pages_to_check ),
|
||
|
'post_type' => 'page',
|
||
|
'fields' => 'ids',
|
||
|
)
|
||
|
);
|
||
|
|
||
|
// Default value for checkout page
|
||
|
$checkout = 0;
|
||
|
|
||
|
// We'll only update settings on change
|
||
|
$changed = false;
|
||
|
|
||
|
// Use the current user as the page author.
|
||
|
$user_id = get_current_user_id();
|
||
|
|
||
|
// Loop through all pages, fix or create any missing ones
|
||
|
foreach ( $pages as $page => $page_attributes ) {
|
||
|
|
||
|
$page_attributes = wp_parse_args(
|
||
|
$page_attributes,
|
||
|
array(
|
||
|
'post_status' => 'publish',
|
||
|
'post_author' => $user_id,
|
||
|
'post_type' => 'page',
|
||
|
'comment_status' => 'closed',
|
||
|
)
|
||
|
);
|
||
|
|
||
|
$page_id = ! empty( $pages_to_check[ $page ] ) ? $pages_to_check[ $page ] : false;
|
||
|
|
||
|
// Checks if the page option exists
|
||
|
$page_object = ! array_key_exists( $page, $missing_pages ) && ! empty( $posts->posts ) && ! empty( $page_id )
|
||
|
? get_post( $page_id )
|
||
|
: array();
|
||
|
|
||
|
// Skip if page exists
|
||
|
if ( ! empty( $page_object ) ) {
|
||
|
|
||
|
// Set the checkout page
|
||
|
if ( 'purchase_page' === $page ) {
|
||
|
$checkout = $page_object->ID;
|
||
|
}
|
||
|
|
||
|
// Skip if page exists
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( ! isset( $page_attributes['post_parent'] ) ) {
|
||
|
$page_attributes['post_parent'] = $checkout;
|
||
|
}
|
||
|
|
||
|
// Create the new page
|
||
|
$new_page = wp_insert_post( $page_attributes );
|
||
|
|
||
|
// Update the checkout page ID
|
||
|
if ( 'purchase_page' === $page ) {
|
||
|
$checkout = $new_page;
|
||
|
}
|
||
|
|
||
|
// Set the page option
|
||
|
$current_options[ $page ] = $new_page;
|
||
|
|
||
|
// Pages changed
|
||
|
$changed = true;
|
||
|
}
|
||
|
|
||
|
// Update the option
|
||
|
if ( true === $changed ) {
|
||
|
update_option( 'edd_settings', $current_options );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the array of required pages with default attributes and content for EDD.
|
||
|
*
|
||
|
* @since 3.1
|
||
|
* @return array
|
||
|
*/
|
||
|
function edd_get_required_pages() {
|
||
|
|
||
|
return apply_filters(
|
||
|
'edd_required_pages',
|
||
|
array(
|
||
|
'purchase_page' => array(
|
||
|
'post_title' => __( 'Checkout', 'easy-digital-downloads' ),
|
||
|
'post_content' => '<!-- wp:shortcode -->[download_checkout]<!-- /wp:shortcode -->',
|
||
|
'post_parent' => 0,
|
||
|
),
|
||
|
'success_page' => array(
|
||
|
'post_title' => __( 'Purchase Confirmation', 'easy-digital-downloads' ),
|
||
|
'post_content' => '<!-- wp:paragraph --><p>' . __( 'Thank you for your purchase!', 'easy-digital-downloads' ) . '</p><!-- /wp:paragraph --><!-- wp:shortcode -->[edd_receipt]<!-- /wp:shortcode -->',
|
||
|
),
|
||
|
'failure_page' => array(
|
||
|
'post_title' => __( 'Transaction Failed', 'easy-digital-downloads' ),
|
||
|
'post_content' => '<!-- wp:paragraph --><p>' . __( 'Your transaction failed; please try again or contact site support.', 'easy-digital-downloads' ) .'</p><!-- /wp:paragraph -->',
|
||
|
),
|
||
|
'purchase_history_page' => array(
|
||
|
'post_title' => __( 'Purchase History', 'easy-digital-downloads' ),
|
||
|
'post_content' => '<!-- wp:shortcode -->[purchase_history]<!-- /wp:shortcode -->',
|
||
|
),
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Install the default settings
|
||
|
*
|
||
|
* @since 3.0
|
||
|
*
|
||
|
* @global array $edd_options
|
||
|
*/
|
||
|
function edd_install_settings() {
|
||
|
global $edd_options;
|
||
|
|
||
|
// Setup some default options
|
||
|
$options = array();
|
||
|
|
||
|
// Populate some default values
|
||
|
$all_settings = edd_get_registered_settings();
|
||
|
|
||
|
if ( ! empty( $all_settings ) ) {
|
||
|
foreach ( $all_settings as $tab => $sections ) {
|
||
|
foreach ( $sections as $section => $settings) {
|
||
|
|
||
|
// Check for backwards compatibility
|
||
|
$tab_sections = edd_get_settings_tab_sections( $tab );
|
||
|
if ( ! is_array( $tab_sections ) || ! array_key_exists( $section, $tab_sections ) ) {
|
||
|
$section = 'main';
|
||
|
$settings = $sections;
|
||
|
}
|
||
|
|
||
|
foreach ( $settings as $option ) {
|
||
|
if ( ! empty( $option['type'] ) && 'checkbox' == $option['type'] && ! empty( $option['std'] ) ) {
|
||
|
$options[ $option['id'] ] = '1';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Get the settings
|
||
|
$settings = get_option( 'edd_settings', array() );
|
||
|
$merged_options = array_merge( $settings, $options );
|
||
|
$edd_options = $merged_options;
|
||
|
|
||
|
// Update the settings
|
||
|
update_option( 'edd_settings', $merged_options );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* When a new Blog is created in multisite, see if EDD is network activated, and run the installer
|
||
|
*
|
||
|
* @since 2.5
|
||
|
* @param int|WP_Site $blog WordPress 5.1 passes a WP_Site object.
|
||
|
* @return void
|
||
|
*/
|
||
|
function edd_new_blog_created( $blog ) {
|
||
|
|
||
|
// Bail if plugin is not activated for the network
|
||
|
if ( ! is_plugin_active_for_network( plugin_basename( EDD_PLUGIN_FILE ) ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( ! is_int( $blog ) ) {
|
||
|
$blog = $blog->id;
|
||
|
}
|
||
|
|
||
|
switch_to_blog( $blog );
|
||
|
edd_install();
|
||
|
restore_current_blog();
|
||
|
}
|
||
|
if ( version_compare( get_bloginfo( 'version' ), '5.1', '>=' ) ) {
|
||
|
add_action( 'wp_initialize_site', 'edd_new_blog_created' );
|
||
|
} else {
|
||
|
add_action( 'wpmu_new_blog', 'edd_new_blog_created' );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Drop our custom tables when a mu site is deleted
|
||
|
*
|
||
|
* @deprecated 3.0 Handled by WP_DB_Table
|
||
|
* @since 2.5
|
||
|
* @param array $tables The tables to drop
|
||
|
* @param int $blog_id The Blog ID being deleted
|
||
|
* @return array The tables to drop
|
||
|
*/
|
||
|
function edd_wpmu_drop_tables( $tables, $blog_id ) {
|
||
|
|
||
|
switch_to_blog( $blog_id );
|
||
|
$customers_db = new EDD_DB_Customers();
|
||
|
$customer_meta_db = new EDD_DB_Customer_Meta();
|
||
|
if ( $customers_db->installed() ) {
|
||
|
$tables[] = $customers_db->table_name;
|
||
|
$tables[] = $customer_meta_db->table_name;
|
||
|
}
|
||
|
restore_current_blog();
|
||
|
|
||
|
return $tables;
|
||
|
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Post-installation
|
||
|
*
|
||
|
* Runs just after plugin installation and exposes the
|
||
|
* edd_after_install hook.
|
||
|
*
|
||
|
* @since 1.7
|
||
|
* @return void
|
||
|
*/
|
||
|
function edd_after_install() {
|
||
|
|
||
|
if ( ! is_admin() ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$edd_options = get_transient( '_edd_installed' );
|
||
|
|
||
|
do_action( 'edd_after_install', $edd_options );
|
||
|
|
||
|
if ( false !== $edd_options ) {
|
||
|
// Delete the transient
|
||
|
delete_transient( '_edd_installed' );
|
||
|
}
|
||
|
}
|
||
|
add_action( 'admin_init', 'edd_after_install' );
|
||
|
|
||
|
/**
|
||
|
* Install user roles on sub-sites of a network
|
||
|
*
|
||
|
* Roles do not get created when EDD is network activation so we need to create them during admin_init
|
||
|
*
|
||
|
* @since 1.9
|
||
|
* @return void
|
||
|
*/
|
||
|
function edd_install_roles_on_network() {
|
||
|
|
||
|
global $wp_roles;
|
||
|
|
||
|
if( ! is_object( $wp_roles ) ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
if( empty( $wp_roles->roles ) || ! array_key_exists( 'shop_manager', $wp_roles->roles ) ) {
|
||
|
|
||
|
// Create EDD shop roles
|
||
|
$roles = new EDD_Roles;
|
||
|
$roles->add_roles();
|
||
|
$roles->add_caps();
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
add_action( 'admin_init', 'edd_install_roles_on_network' );
|