Hotel Raxa - Advanced Booking System Implementation

🏨 Hotel Booking Enhancements:
- Implemented Eagle Booking Advanced Pricing add-on
- Added Booking.com-style rate management system
- Created professional calendar interface for pricing
- Integrated deals and discounts functionality

💰 Advanced Pricing Features:
- Dynamic pricing models (per room, per person, per adult)
- Base rates, adult rates, and child rates management
- Length of stay discounts and early bird deals
- Mobile rates and secret deals implementation
- Seasonal promotions and flash sales

📅 Availability Management:
- Real-time availability tracking
- Stop sell and restriction controls
- Closed to arrival/departure functionality
- Minimum/maximum stay requirements
- Automatic sold-out management

💳 Payment Integration:
- Maintained Redsys payment gateway integration
- Seamless integration with existing Eagle Booking
- No modifications to core Eagle Booking plugin

🛠️ Technical Implementation:
- Custom database tables for advanced pricing
- WordPress hooks and filters integration
- AJAX-powered admin interface
- Data migration from existing Eagle Booking
- Professional calendar view for revenue management

📊 Admin Interface:
- Booking.com-style management dashboard
- Visual rate and availability calendar
- Bulk operations for date ranges
- Statistics and analytics dashboard
- Modal dialogs for quick editing

🔧 Code Quality:
- WordPress coding standards compliance
- Secure database operations with prepared statements
- Proper input validation and sanitization
- Error handling and logging
- Responsive admin interface

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Hotel Raxa Dev
2025-07-11 07:43:22 +02:00
commit 5b1e2453c7
9816 changed files with 2784509 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,125 @@
<?php
/**
* Upgrader skin classes.
*
* @package Envato_Market
*/
// Include the WP_Upgrader_Skin class.
if ( ! class_exists( 'WP_Upgrader_Skin', false ) ) :
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader-skins.php';
endif;
if ( ! class_exists( 'Envato_Market_Theme_Installer_Skin' ) ) :
/**
* Theme Installer Skin.
*
* @class Envato_Market_Theme_Installer_Skin
* @version 1.0.0
* @since 1.0.0
*/
class Envato_Market_Theme_Installer_Skin extends Theme_Installer_Skin {
/**
* Modify the install actions.
*
* @since 1.0.0
*/
public function after() {
if ( empty( $this->upgrader->result['destination_name'] ) ) {
return;
}
$theme_info = $this->upgrader->theme_info();
if ( empty( $theme_info ) ) {
return;
}
$name = $theme_info->display( 'Name' );
$stylesheet = $this->upgrader->result['destination_name'];
$template = $theme_info->get_template();
$activate_link = add_query_arg(
array(
'action' => 'activate',
'template' => urlencode( $template ),
'stylesheet' => urlencode( $stylesheet ),
),
admin_url( 'themes.php' )
);
$activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet );
$install_actions = array();
if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
$install_actions['preview'] = '<a href="' . wp_customize_url( $stylesheet ) . '" class="hide-if-no-customize load-customize"><span aria-hidden="true">' . __( 'Live Preview', 'envato-market' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Live Preview &#8220;%s&#8221;', 'envato-market' ), $name ) . '</span></a>';
}
if ( is_multisite() ) {
if ( current_user_can( 'manage_network_themes' ) ) {
$install_actions['network_enable'] = '<a href="' . esc_url( network_admin_url( wp_nonce_url( 'themes.php?action=enable&amp;theme=' . urlencode( $stylesheet ) . '&amp;paged=1&amp;s', 'enable-theme_' . $stylesheet ) ) ) . '" target="_parent">' . __( 'Network Enable', 'envato-market' ) . '</a>';
}
}
$install_actions['activate'] = '<a href="' . esc_url( $activate_link ) . '" class="activatelink"><span aria-hidden="true">' . __( 'Activate', 'envato-market' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Activate &#8220;%s&#8221;', 'envato-market' ), $name ) . '</span></a>';
$install_actions['themes_page'] = '<a href="' . esc_url( admin_url( 'admin.php?page=' . envato_market()->get_slug() . '&tab=themes' ) ) . '" target="_parent">' . __( 'Return to Theme Installer', 'envato-market' ) . '</a>';
if ( ! $this->result || is_wp_error( $this->result ) || is_multisite() || ! current_user_can( 'switch_themes' ) ) {
unset( $install_actions['activate'], $install_actions['preview'] );
}
if ( ! empty( $install_actions ) ) {
$this->feedback( implode( ' | ', $install_actions ) );
}
}
}
endif;
if ( ! class_exists( 'Envato_Market_Plugin_Installer_Skin' ) ) :
/**
* Plugin Installer Skin.
*
* @class Envato_Market_Plugin_Installer_Skin
* @version 1.0.0
* @since 1.0.0
*/
class Envato_Market_Plugin_Installer_Skin extends Plugin_Installer_Skin {
/**
* Modify the install actions.
*
* @since 1.0.0
*/
public function after() {
$plugin_file = $this->upgrader->plugin_info();
$install_actions = array();
if ( current_user_can( 'activate_plugins' ) ) {
$install_actions['activate_plugin'] = '<a href="' . esc_url( wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ) ) . '" target="_parent">' . __( 'Activate Plugin', 'envato-market' ) . '</a>';
}
if ( is_multisite() ) {
unset( $install_actions['activate_plugin'] );
if ( current_user_can( 'manage_network_plugins' ) ) {
$install_actions['network_activate'] = '<a href="' . esc_url( network_admin_url( wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $plugin_file ), 'activate-plugin_' . $plugin_file ) ) ) . '" target="_parent">' . __( 'Network Activate', 'envato-market' ) . '</a>';
}
}
$install_actions['plugins_page'] = '<a href="' . esc_url( admin_url( 'admin.php?page=' . envato_market()->get_slug() . '&tab=plugins' ) ) . '" target="_parent">' . __( 'Return to Plugin Installer', 'envato-market' ) . '</a>';
if ( ! $this->result || is_wp_error( $this->result ) ) {
unset( $install_actions['activate_plugin'], $install_actions['site_activate'], $install_actions['network_activate'] );
}
if ( ! empty( $install_actions ) ) {
$this->feedback( implode( ' | ', $install_actions ) );
}
}
}
endif;

View File

@@ -0,0 +1,87 @@
<?php
/**
* Theme Upgrader class.
*
* @package Envato_Market
*/
// Include the WP_Upgrader class.
if ( ! class_exists( 'WP_Upgrader', false ) ) :
include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
endif;
if ( ! class_exists( 'Envato_Market_Theme_Upgrader' ) ) :
/**
* Extends the WordPress Theme_Upgrader class.
*
* This class makes modifications to the strings during install & upgrade.
*
* @class Envato_Market_Plugin_Upgrader
* @version 1.0.0
* @since 1.0.0
*/
class Envato_Market_Theme_Upgrader extends Theme_Upgrader {
/**
* Initialize the upgrade strings.
*
* @since 1.0.0
*/
public function upgrade_strings() {
parent::upgrade_strings();
$this->strings['downloading_package'] = __( 'Downloading the Envato Market upgrade package&#8230;', 'envato-market' );
}
/**
* Initialize the install strings.
*
* @since 1.0.0
*/
public function install_strings() {
parent::install_strings();
$this->strings['downloading_package'] = __( 'Downloading the Envato Market install package&#8230;', 'envato-market' );
}
}
endif;
if ( ! class_exists( 'Envato_Market_Plugin_Upgrader' ) ) :
/**
* Extends the WordPress Plugin_Upgrader class.
*
* This class makes modifications to the strings during install & upgrade.
*
* @class Envato_Market_Plugin_Upgrader
* @version 1.0.0
* @since 1.0.0
*/
class Envato_Market_Plugin_Upgrader extends Plugin_Upgrader {
/**
* Initialize the upgrade strings.
*
* @since 1.0.0
*/
public function upgrade_strings() {
parent::upgrade_strings();
$this->strings['downloading_package'] = __( 'Downloading the Envato Market upgrade package&#8230;', 'envato-market' );
}
/**
* Initialize the install strings.
*
* @since 1.0.0
*/
public function install_strings() {
parent::install_strings();
$this->strings['downloading_package'] = __( 'Downloading the Envato Market install package&#8230;', 'envato-market' );
}
}
endif;

View File

@@ -0,0 +1,478 @@
<?php
/**
* Functions
*
* @package Envato_Market
*/
/**
* Interate over the themes array and displays each theme.
*
* @since 1.0.0
*
* @param string $group The theme group. Options are 'purchased', 'active', 'installed', or 'install'.
*/
function envato_market_themes_column( $group = 'install' ) {
$premium = envato_market()->items()->themes( $group );
if ( empty( $premium ) ) {
return;
}
foreach ( $premium as $slug => $theme ) :
$name = $theme['name'];
$author = $theme['author'];
$version = $theme['version'];
$description = $theme['description'];
$url = $theme['url'];
$author_url = $theme['author_url'];
$theme['hasUpdate'] = false;
if ( 'active' === $group || 'installed' === $group ) {
$get_theme = wp_get_theme( $slug );
if ( $get_theme->exists() ) {
$name = $get_theme->get( 'Name' );
$author = $get_theme->get( 'Author' );
$version = $get_theme->get( 'Version' );
$description = $get_theme->get( 'Description' );
$author_url = $get_theme->get( 'AuthorURI' );
if ( version_compare( $version, $theme['version'], '<' ) ) {
$theme['hasUpdate'] = true;
}
}
}
// Setup the column CSS classes.
$classes = array( 'envato-card', 'theme' );
if ( 'active' === $group ) {
$classes[] = 'active';
}
// Setup the update action links.
$update_actions = array();
if ( true === $theme['hasUpdate'] ) {
$classes[] = 'update';
$classes[] = 'envato-card-' . esc_attr( $slug );
if ( current_user_can( 'update_themes' ) ) {
// Upgrade link.
$upgrade_link = add_query_arg(
array(
'action' => 'upgrade-theme',
'theme' => esc_attr( $slug ),
),
self_admin_url( 'update.php' )
);
$update_actions['update'] = sprintf(
'<a class="update-now" href="%1$s" aria-label="%2$s" data-name="%3$s %5$s" data-slug="%4$s" data-version="%5$s">%6$s</a>',
wp_nonce_url( $upgrade_link, 'upgrade-theme_' . $slug ),
esc_attr__( 'Update %s now', 'envato-market' ),
esc_attr( $name ),
esc_attr( $slug ),
esc_attr( $theme['version'] ),
esc_html__( 'Update Available', 'envato-market' )
);
$update_actions['details'] = sprintf(
'<a href="%1$s" class="details" title="%2$s" target="_blank">%3$s</a>',
esc_url( $url ),
esc_attr( $name ),
sprintf(
__( 'View version %1$s details.', 'envato-market' ),
$theme['version']
)
);
}
}
// Setup the action links.
$actions = array();
if ( 'active' === $group && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
// Customize theme.
$customize_url = admin_url( 'customize.php' );
$customize_url .= '?theme=' . urlencode( $slug );
$customize_url .= '&return=' . urlencode( envato_market()->get_page_url() . '#themes' );
$actions['customize'] = '<a href="' . esc_url( $customize_url ) . '" class="button button-primary load-customize hide-if-no-customize"><span aria-hidden="true">' . __( 'Customize', 'envato-market' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Customize &#8220;%s&#8221;', 'envato-market' ), $name ) . '</span></a>';
} elseif ( 'installed' === $group ) {
$can_activate = true;
// @codeCoverageIgnoreStart
// Multisite needs special attention.
if ( is_multisite() && ! $get_theme->is_allowed( 'both' ) && current_user_can( 'manage_sites' ) ) {
$can_activate = false;
if ( current_user_can( 'manage_network_themes' ) ) {
$actions['network_enable'] = '<a href="' . esc_url( network_admin_url( wp_nonce_url( 'themes.php?action=enable&amp;theme=' . urlencode( $slug ) . '&amp;paged=1&amp;s', 'enable-theme_' . $slug ) ) ) . '" class="button"><span aria-hidden="true">' . __( 'Network Enable', 'envato-market' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Network Enable &#8220;%s&#8221;', 'envato-market' ), $name ) . '</span></a>';
}
}
// @codeCoverageIgnoreEnd
// Can activate theme.
if ( $can_activate && current_user_can( 'switch_themes' ) ) {
$activate_link = add_query_arg(
array(
'action' => 'activate',
'stylesheet' => urlencode( $slug ),
),
admin_url( 'themes.php' )
);
$activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $slug );
// Activate link.
$actions['activate'] = '<a href="' . esc_url( $activate_link ) . '" class="button"><span aria-hidden="true">' . __( 'Activate', 'envato-market' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Activate &#8220;%s&#8221;', 'envato-market' ), $name ) . '</span></a>';
// Preview theme.
if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) {
$preview_url = admin_url( 'customize.php' );
$preview_url .= '?theme=' . urlencode( $slug );
$preview_url .= '&return=' . urlencode( envato_market()->get_page_url() . '#themes' );
$actions['customize_preview'] = '<a href="' . esc_url( $preview_url ) . '" class="button button-primary load-customize hide-if-no-customize"><span aria-hidden="true">' . __( 'Live Preview', 'envato-market' ) . '</span><span class="screen-reader-text">' . sprintf( __( 'Live Preview &#8220;%s&#8221;', 'envato-market' ), $name ) . '</span></a>';
}
}
} elseif ( 'install' === $group && current_user_can( 'install_themes' ) ) {
// Install link.
$install_link = add_query_arg(
array(
'page' => envato_market()->get_slug(),
'action' => 'install-theme',
'id' => $theme['id'],
),
self_admin_url( 'admin.php' )
);
$actions['install'] = '
<a href="' . wp_nonce_url( $install_link, 'install-theme_' . $theme['id'] ) . '" class="button button-primary">
<span aria-hidden="true">' . __( 'Install', 'envato-market' ) . '</span>
<span class="screen-reader-text">' . sprintf( __( 'Install %s', 'envato-market' ), $name ) . '</span>
</a>';
}
if ( 0 === strrpos( html_entity_decode( $author ), '<a ' ) ) {
$author_link = $author;
} else {
$author_link = '<a href="' . esc_url( $author_url ) . '">' . esc_html( $author ) . '</a>';
}
?>
<div class="envato-market-block" data-id="<?php echo esc_attr( $theme['id'] ); ?>">
<div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
<div class="envato-card-top">
<a href="<?php echo esc_url( $url ); ?>" class="column-icon">
<img src="<?php echo esc_url( $theme['thumbnail_url'] ); ?>"/>
</a>
<div class="column-name">
<h4>
<a href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( $name ); ?></a>
<span class="version" aria-label="<?php esc_attr_e( 'Version %s', 'envato-market' ); ?>">
<?php echo esc_html( sprintf( __( 'Version %s', 'envato-market' ), $version ) ); ?>
</span>
</h4>
</div>
<div class="column-description">
<div class="description">
<?php echo wp_kses_post( wpautop( strip_tags( $description ) ) ); ?>
</div>
<p class="author">
<cite>
<?php esc_html_e( 'By', 'envato-market' ); ?>
<?php echo wp_kses_post( $author_link ); ?>
</cite>
</p>
</div>
<?php if ( ! empty( $update_actions ) ) { ?>
<div class="column-update">
<?php echo implode( "\n", $update_actions ); ?>
</div>
<?php } ?>
</div>
<div class="envato-card-bottom">
<div class="column-rating">
<?php
if ( ! empty( $theme['rating'] ) ) {
if ( is_array( $theme['rating'] ) ) {
$count = ! empty( $theme['rating']['count'] ) ? $theme['rating']['count'] : 0;
$rating = ! empty( $theme['rating']['rating'] ) ? (int) $theme['rating']['rating'] : 0;
wp_star_rating(
array(
'rating' => $count > 0 ? ( $rating / 5 * 100 ) : 0,
'type' => 'percent',
'number' => $count,
)
);
} else {
wp_star_rating(
array(
'rating' => $theme['rating'] > 0 ? ( $theme['rating'] / 5 * 100 ) : 0,
'type' => 'percent',
)
);
}
}
?>
</div>
<div class="column-actions">
<?php echo implode( "\n", $actions ); ?>
</div>
</div>
</div>
</div>
<?php
endforeach;
}
/**
* Interate over the plugins array and displays each plugin.
*
* @since 1.0.0
*
* @param string $group The plugin group. Options are 'purchased', 'active', 'installed', or 'install'.
*/
function envato_market_plugins_column( $group = 'install' ) {
$premium = envato_market()->items()->plugins( $group );
if ( empty( $premium ) ) {
return;
}
$plugins = envato_market()->items()->wp_plugins();
foreach ( $premium as $slug => $plugin ) :
$name = $plugin['name'];
$author = $plugin['author'];
$version = $plugin['version'];
$description = $plugin['description'];
$url = $plugin['url'];
$author_url = $plugin['author_url'];
$plugin['hasUpdate'] = false;
// Setup the column CSS classes.
$classes = array( 'envato-card', 'plugin' );
if ( 'active' === $group ) {
$classes[] = 'active';
}
// Setup the update action links.
$update_actions = array();
// Check for an update.
if ( isset( $plugins[ $slug ] ) && version_compare( $plugins[ $slug ]['Version'], $plugin['version'], '<' ) ) {
$plugin['hasUpdate'] = true;
$classes[] = 'update';
$classes[] = 'envato-card-' . sanitize_key( dirname( $slug ) );
if ( current_user_can( 'update_plugins' ) ) {
// Upgrade link.
$upgrade_link = add_query_arg(
array(
'action' => 'upgrade-plugin',
'plugin' => $slug,
),
self_admin_url( 'update.php' )
);
// Details link.
$details_link = add_query_arg(
array(
'action' => 'upgrade-plugin',
'tab' => 'plugin-information',
'plugin' => dirname( $slug ),
'section' => 'changelog',
'TB_iframe' => 'true',
'width' => 640,
'height' => 662,
),
self_admin_url( 'plugin-install.php' )
);
$update_actions['update'] = sprintf(
'<a class="update-now" href="%1$s" aria-label="%2$s" data-name="%3$s %6$s" data-plugin="%4$s" data-slug="%5$s" data-version="%6$s">%7$s</a>',
wp_nonce_url( $upgrade_link, 'upgrade-plugin_' . $slug ),
esc_attr__( 'Update %s now', 'envato-market' ),
esc_attr( $name ),
esc_attr( $slug ),
sanitize_key( dirname( $slug ) ),
esc_attr( $version ),
esc_html__( 'Update Available', 'envato-market' )
);
$update_actions['details'] = sprintf(
'<a href="%1$s" class="thickbox details" title="%2$s">%3$s</a>',
esc_url( $details_link ),
esc_attr( $name ),
sprintf(
__( 'View version %1$s details.', 'envato-market' ),
$version
)
);
}
}
// Setup the action links.
$actions = array();
if ( 'active' === $group ) {
// Deactivate link.
$deactivate_link = add_query_arg(
array(
'action' => 'deactivate',
'plugin' => $slug,
),
self_admin_url( 'plugins.php' )
);
$actions['deactivate'] = '
<a href="' . wp_nonce_url( $deactivate_link, 'deactivate-plugin_' . $slug ) . '" class="button">
<span aria-hidden="true">' . __( 'Deactivate', 'envato-market' ) . '</span>
<span class="screen-reader-text">' . sprintf( __( 'Deactivate %s', 'envato-market' ), $name ) . '</span>
</a>';
} elseif ( 'installed' === $group ) {
if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) {
// Delete link.
$delete_link = add_query_arg(
array(
'action' => 'delete-selected',
'checked[]' => $slug,
),
self_admin_url( 'plugins.php' )
);
$actions['delete'] = '
<a href="' . wp_nonce_url( $delete_link, 'bulk-plugins' ) . '" class="button-delete">
<span aria-hidden="true">' . __( 'Delete', 'envato-market' ) . '</span>
<span class="screen-reader-text">' . sprintf( __( 'Delete %s', 'envato-market' ), $name ) . '</span>
</a>';
}
if ( ! is_multisite() && current_user_can( 'activate_plugins' ) ) {
// Activate link.
$activate_link = add_query_arg(
array(
'action' => 'activate',
'plugin' => $slug,
),
self_admin_url( 'plugins.php' )
);
$actions['activate'] = '
<a href="' . wp_nonce_url( $activate_link, 'activate-plugin_' . $slug ) . '" class="button">
<span aria-hidden="true">' . __( 'Activate', 'envato-market' ) . '</span>
<span class="screen-reader-text">' . sprintf( __( 'Activate %s', 'envato-market' ), $name ) . '</span>
</a>';
}
// @codeCoverageIgnoreStart
// Multisite needs special attention.
if ( is_multisite() ) {
if ( current_user_can( 'manage_network_plugins' ) ) {
$actions['network_activate'] = '
<a href="' . esc_url( network_admin_url( wp_nonce_url( 'plugins.php?action=activate&amp;plugin=' . urlencode( $slug ), 'activate-plugin_' . $slug ) ) ) . '" class="button">
<span aria-hidden="true">' . __( 'Network Activate', 'envato-market' ) . '</span>
<span class="screen-reader-text">' . sprintf( __( 'Network Activate %s', 'envato-market' ), $name ) . '</span>
</a>';
}
}
// @codeCoverageIgnoreEnd
} elseif ( 'install' === $group && current_user_can( 'install_plugins' ) ) {
// Install link.
$install_link = add_query_arg(
array(
'page' => envato_market()->get_slug(),
'action' => 'install-plugin',
'id' => $plugin['id'],
),
self_admin_url( 'admin.php' )
);
$actions['install'] = '
<a href="' . wp_nonce_url( $install_link, 'install-plugin_' . $plugin['id'] ) . '" class="button button-primary">
<span aria-hidden="true">' . __( 'Install', 'envato-market' ) . '</span>
<span class="screen-reader-text">' . sprintf( __( 'Install %s', 'envato-market' ), $name ) . '</span>
</a>';
}
if ( 0 === strrpos( html_entity_decode( $author ), '<a ' ) ) {
$author_link = $author;
} else {
$author_link = '<a href="' . esc_url( $author_url ) . '">' . esc_html( $author ) . '</a>';
}
?>
<div class="envato-market-block" data-id="<?php echo esc_attr( $plugin['id'] ); ?>">
<div class="<?php echo esc_attr( implode( ' ', $classes ) ); ?>">
<div class="envato-card-top">
<a href="<?php echo esc_url( $url ); ?>" class="column-icon">
<img src="<?php echo esc_url( $plugin['thumbnail_url'] ); ?>"/>
</a>
<div class="column-name">
<h4>
<a href="<?php echo esc_url( $url ); ?>"><?php echo esc_html( $name ); ?></a>
<span class="version" aria-label="<?php esc_attr_e( 'Version %s', 'envato-market' ); ?>">
<?php echo esc_html( sprintf( __( 'Version %s', 'envato-market' ), ( isset( $plugins[ $slug ] ) ? $plugins[ $slug ]['Version'] : $version ) ) ); ?>
</span>
</h4>
</div>
<div class="column-description">
<div class="description">
<?php echo wp_kses_post( wpautop( strip_tags( $description ) ) ); ?>
</div>
<p class="author">
<cite>
<?php esc_html_e( 'By', 'envato-market' ); ?>
<?php echo wp_kses_post( $author_link ); ?>
</cite>
</p>
</div>
<?php if ( ! empty( $update_actions ) ) { ?>
<div class="column-update">
<?php echo implode( "\n", $update_actions ); ?>
</div>
<?php } ?>
</div>
<div class="envato-card-bottom">
<div class="column-rating">
<?php
if ( ! empty( $plugin['rating'] ) ) {
if ( is_array( $plugin['rating'] ) && ! empty( $plugin['rating']['count'] ) ) {
wp_star_rating(
array(
'rating' => $plugin['rating']['rating'] > 0 ? ( $plugin['rating']['rating'] / 5 * 100 ) : 0,
'type' => 'percent',
'number' => $plugin['rating']['count'],
)
);
} else {
wp_star_rating(
array(
'rating' => $plugin['rating'] > 0 ? ( $plugin['rating'] / 5 * 100 ) : 0,
'type' => 'percent',
)
);
}
}
?>
</div>
<div class="column-actions">
<?php echo implode( "\n", $actions ); ?>
</div>
</div>
</div>
</div>
<?php
endforeach;
}
/**
* A handy method for logging to the st_out / and or debug_log
* Use: write_log("My variable is {$variable}")
*/
if (!function_exists('write_log') && defined('ENVATO_LOCAL_DEVELOPMENT')) {
function write_log($log) {
if (is_array($log) || is_object($log)) {
error_log(print_r($log, true));
} else {
error_log($log);
}
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* Admin UI
*
* @package Envato_Market
* @since 1.0.0
*/
if ( isset( $_GET['action'] ) ) {
$id = ! empty( $_GET['id'] ) ? absint( trim( $_GET['id'] ) ) : '';
if ( 'install-plugin' === $_GET['action'] ) {
Envato_Market_Admin::install_plugin( $id );
} elseif ( 'install-theme' === $_GET['action'] ) {
Envato_Market_Admin::install_theme( $id );
}
} else {
add_thickbox();
?>
<div class="wrap about-wrap full-width-layout">
<?php Envato_Market_Admin::render_intro_partial(); ?>
<?php Envato_Market_Admin::render_tabs_partial(); ?>
<form method="POST" action="<?php echo esc_url( ENVATO_MARKET_NETWORK_ACTIVATED ? network_admin_url( 'edit.php?action=envato_market_network_settings' ) : admin_url( 'options.php' ) ); ?>">
<?php Envato_Market_Admin::render_themes_panel_partial(); ?>
<?php Envato_Market_Admin::render_plugins_panel_partial(); ?>
<?php Envato_Market_Admin::render_settings_panel_partial(); ?>
<?php Envato_Market_Admin::render_help_panel_partial(); ?>
</form>
</div>
<?php
}

View File

@@ -0,0 +1,12 @@
<?php
/**
* Items section
*
* @package Envato_Market
* @since 1.0.0
*/
?>
<p><?php esc_html_e( 'Add Envato Market themes & plugins using multiple OAuth tokens. This is especially useful when an item has been purchased on behalf of a third-party. This works similarly to the global OAuth Personal Token, but for individual items and additionally requires the Envato Market item ID.', 'envato-market' ); ?></p>
<p><?php esc_html_e( 'Warning: These tokens can be revoked by the account holder at any time.', 'envato-market' ); ?></p>

View File

@@ -0,0 +1,30 @@
<?php
/**
* OAuth section
*
* @package Envato_Market
* @since 1.0.0
*/
?>
<p>
<?php printf( esc_html__( 'This area enables WordPress Theme &amp; Plugin updates from Envato Market. Read more about how this process works at %s.', 'envato-market' ), '<a href="https://envato.com/market-plugin/" target="_blank">' . esc_html__( 'envato.com', 'envato-market' ) . '</a>' ); ?>
</p>
<p>
<?php esc_html_e( 'Please follow the steps below:', 'envato-market' ); ?>
</p>
<ol>
<li><?php printf( esc_html__( 'Generate an Envato API Personal Token by %s.', 'envato-market' ), '<a href="' . envato_market()->admin()->get_generate_token_url() . '" target="_blank">' . esc_html__( 'clicking this link', 'envato-market' ) . '</a>' ); ?></li>
<li><?php esc_html_e( 'Name the token eg “My WordPress site”.', 'envato-market' ); ?></li>
<li><?php esc_html_e( 'Ensure the following permissions are enabled:', 'envato-market' ); ?>
<ul>
<li><?php esc_html_e( 'View and search Envato sites', 'envato-market' ); ?></li>
<li><?php esc_html_e( 'Download your purchased items', 'envato-market' ); ?></li>
<li><?php esc_html_e( 'List purchases you\'ve made', 'envato-market' ); ?></li>
</ul>
</li>
<li><?php esc_html_e( 'Copy the token into the box below.', 'envato-market' ); ?></li>
<li><?php esc_html_e( 'Click the "Save Changes" button.', 'envato-market' ); ?></li>
<li><?php esc_html_e( 'A list of purchased Themes &amp; Plugins from Envato Market will appear.', 'envato-market' ); ?></li>
</ol>

View File

@@ -0,0 +1,37 @@
<?php
/**
* Items setting
*
* @package Envato_Market
* @since 1.0.0
*/
$items = envato_market()->get_option( 'items', array() );
?>
<ul id="envato-market-items">
<?php
if ( ! empty( $items ) ) {
foreach ( $items as $key => $item ) {
if ( empty( $item['name'] ) || empty( $item['token'] ) || empty( $item['id'] ) || empty( $item['type'] ) || empty( $item['authorized'] ) ) {
continue;
}
$class = 'success' === $item['authorized'] ? 'is-authorized' : 'not-authorized';
echo '
<li data-id="' . esc_attr( $item['id'] ) . '" class="' . esc_attr( $class ) . '">
<span class="item-name">' . esc_html__( 'ID', 'envato-market' ) . ': ' . esc_html( $item['id'] ) . ' - ' . esc_html( $item['name'] ) . '</span>
<button class="item-delete dashicons dashicons-dismiss">
<span class="screen-reader-text">' . esc_html__( 'Delete', 'envato-market' ) . '</span>
</button>
<input type="hidden" name="' . esc_attr( envato_market()->get_option_name() ) . '[items][' . esc_attr( $key ) . '][name]" value="' . esc_html( $item['name'] ) . '" />
<input type="hidden" name="' . esc_attr( envato_market()->get_option_name() ) . '[items][' . esc_attr( $key ) . '][token]" value="' . esc_html( $item['token'] ) . '" />
<input type="hidden" name="' . esc_attr( envato_market()->get_option_name() ) . '[items][' . esc_attr( $key ) . '][id]" value="' . esc_html( $item['id'] ) . '" />
<input type="hidden" name="' . esc_attr( envato_market()->get_option_name() ) . '[items][' . esc_attr( $key ) . '][type]" value="' . esc_html( $item['type'] ) . '" />
<input type="hidden" name="' . esc_attr( envato_market()->get_option_name() ) . '[items][' . esc_attr( $key ) . '][authorized]" value="' . esc_html( $item['authorized'] ) . '" />
</li>';
}
}
?>
</ul>
<button class="button add-envato-market-item"><?php esc_html_e( 'Add Item', 'envato-market' ); ?></button>

View File

@@ -0,0 +1,12 @@
<?php
/**
* Token setting
*
* @package Envato_Market
* @since 1.0.0
*/
?>
<input type="text" name="<?php echo esc_attr( envato_market()->get_option_name() ); ?>[token]" class="widefat" value="<?php echo esc_html( envato_market()->get_option( 'token' ) ); ?>" autocomplete="off">
<p class="description"><?php esc_html_e( 'Enter your Envato API Personal Token.', 'envato-market' ); ?></p>

View File

@@ -0,0 +1,12 @@
<?php
/**
* Error details
*
* @package Envato_Market
* @since 2.0.2
*/
?>
<div class="notice notice-error is-dismissible">
<p><?php printf( '<strong>Additional Error Details:</strong><br/>%s.<br/> %s <br/> %s', esc_html( $title ), esc_html( $message ), esc_html( json_encode( $data ) ) ); ?></p>
</div>

View File

@@ -0,0 +1,12 @@
<?php
/**
* Error notice
*
* @package Envato_Market
* @since 2.0.1
*/
?>
<div class="notice notice-error is-dismissible">
<p><?php esc_html_e( 'Failed to connect to the Envato API. Please contact the hosting providier with this message: "The Envato Market WordPress plugin requires TLS version 1.2 or above, please confirm if this hosting account supports TLS version 1.2 and allows connections from WordPress to the host api.envato.com".', 'envato-market' ); ?></p>
</div>

View File

@@ -0,0 +1,12 @@
<?php
/**
* Error notice
*
* @package Envato_Market
* @since 2.0.1
*/
?>
<div class="notice notice-error is-dismissible">
<p><?php printf( esc_html__( 'Failed to locate the package file for this item. Please contact the item author for support, or install/upgrade the item manually from the %s.', 'envato-market' ), '<a href="https://themeforest.net/downloads" target="_blank">downloads page</a>' ); ?></p>
</div>

View File

@@ -0,0 +1,18 @@
<?php
/**
* Error notice
*
* @package Envato_Market
* @since 2.0.1
*/
?>
<div class="notice notice-error is-dismissible">
<p><?php printf( esc_html__( 'Incorrect token permissions, please generate another token or fix the permissions on the existing token.' ) ); ?></p>
<p><?php printf( esc_html__( 'Please ensure only the following permissions are enabled: ', 'envato-market' ) ); ?></p>
<ol>
<?php foreach ( $this->get_required_permissions() as $permission ) { ?>
<li><?php echo esc_html( $permission ); ?></li>
<?php } ?>
</ol>
</div>

View File

@@ -0,0 +1,12 @@
<?php
/**
* Error notice
*
* @package Envato_Market
* @since 1.0.0
*/
?>
<div class="notice notice-error is-dismissible">
<p><?php esc_html_e( 'One or more Single Use OAuth Personal Tokens could not be verified and should be removed.', 'envato-market' ); ?></p>
</div>

View File

@@ -0,0 +1,12 @@
<?php
/**
* Error notice
*
* @package Envato_Market
* @since 1.0.0
*/
?>
<div class="notice notice-error is-dismissible">
<p><?php esc_html_e( 'The OAuth Personal Token could not be verified. Please check that the Token has been entered correctly and has the minimum required permissions.', 'envato-market' ); ?></p>
</div>

View File

@@ -0,0 +1,12 @@
<?php
/**
* Success notice
*
* @package Envato_Market
* @since 1.0.0
*/
?>
<div class="notice notice-success is-dismissible">
<p><?php esc_html_e( 'Your OAuth Personal Token has been verified. However, there are no WordPress downloadable items in your account.', 'envato-market' ); ?></p>
</div>

View File

@@ -0,0 +1,12 @@
<?php
/**
* Success notice
*
* @package Envato_Market
* @since 1.0.0
*/
?>
<div class="notice notice-success is-dismissible">
<p><?php esc_html_e( 'All Single Use OAuth Personal Tokens have been verified.', 'envato-market' ); ?></p>
</div>

View File

@@ -0,0 +1,12 @@
<?php
/**
* Success notice
*
* @package Envato_Market
* @since 1.0.0
*/
?>
<div class="notice notice-success is-dismissible">
<p><?php esc_html_e( 'Your OAuth Personal Token has been verified.', 'envato-market' ); ?></p>
</div>

View File

@@ -0,0 +1,46 @@
<?php
/**
* Help panel partial
*
* @package Envato_Market
* @since 2.0.1
*/
?>
<div id="help" class="panel">
<div class="envato-market-blocks">
<div class="envato-market-block">
<h3>Troubleshooting:</h3>
<p>If youre having trouble with the plugin, please</p>
<ol>
<li>Confirm the old <code>Envato Toolkit</code> plugin is not installed.</li>
<li>Confirm the latest version of WordPress is installed.</li>
<li>Confirm the latest version of the <a href="https://envato.com/market-plugin/" target="_blank">Envato Market</a> plugin is installed.</li>
<li>Try creating a new API token has from the <a href="<?php echo envato_market()->admin()->get_generate_token_url(); ?>" target="_blank">build.envato.com</a> website - ensure only the following permissions have been granted
<ul>
<li>View and search Envato sites</li>
<li>Download your purchased items</li>
<li>List purchases you've made</li>
</ul>
</li>
<li>Check with the hosting provider to ensure the API connection to <code>api.envato.com</code> is not blocked.</li>
<li>Check with the hosting provider that the minimum TLS version is 1.2 or above on the server.</li>
<li>If you cant see your items - check with the item author to confirm the Theme or Plugin is compatible with the Envato Market plugin.</li>
<li>Confirm your Envato account is still active and the items are still visible from <a href="https://themeforest.net/downloads" target="_blank">your downloads page</a>.</li>
<li>Note - if an item has been recently updated, it may take up to 24 hours for the latest version to appear in the Envato Market plugin.</li>
</ol>
</div>
<div class="envato-market-block">
<h3>Health Check:</h3>
<div class="envato-market-healthcheck">
Problem starting healthcheck. Please check javascript console for errors.
</div>
<h3>Support:</h3>
<p>The Envato Market plugin is maintained - we ensure it works best on the latest version of WordPress and on a modern hosting platform, however we cant guarantee itll work on all WordPress sites or hosting environments.</p>
<p>If youve tried all the troubleshooting steps and youre still unable to get the Envato Market plugin to work on your site/hosting, at this time, our advice is to remove the Envato Market plugin and instead visit the Downloads section of ThemeForest/CodeCanyon to download the latest version of your items.</p>
<p>If youre having trouble with a specific item from ThemeForest or CodeCanyon, its best you browse to the Theme or Plugin item page, visit the support tab and follow the next steps.
</p>
</div>
</div>
</div>

View File

@@ -0,0 +1,16 @@
<?php
/**
* Intro partial
*
* @package Envato_Market
* @since 1.0.0
*/
?>
<div class="col">
<h1 class="about-title"><img class="about-logo" src="<?php echo envato_market()->get_plugin_url(); ?>images/envato-market-logo.svg" alt="Envato Market"><sup><?php echo esc_html( envato_market()->get_version() ); ?></sup></h1>
<p><?php esc_html_e( 'Welcome!', 'envato-market' ); ?></p>
<p><?php esc_html_e( 'This plugin can install WordPress themes and plugins purchased from ThemeForest & CodeCanyon by connecting with the Envato Market API using a secure OAuth personal token. Once your themes & plugins are installed WordPress will periodically check for updates, so keeping your items up to date is as simple as a few clicks.', 'envato-market' ); ?></p>
<p><strong><?php printf( esc_html__( 'Find out more at %1$senvato.com%2$s.', 'envato-market' ), '<a href="https://envato.com/market-plugin/" target="_blank">', '</a>' ); ?></strong></p>
</div>

View File

@@ -0,0 +1,22 @@
<?php
/**
* Plugins panel partial
*
* @package Envato_Market
* @since 1.0.0
*/
$plugins = envato_market()->items()->plugins( 'purchased' );
?>
<div id="plugins" class="panel <?php echo empty( $plugins ) ? 'hidden' : ''; ?>">
<div class="envato-market-blocks">
<?php
if ( ! empty( $plugins ) ) {
envato_market_plugins_column( 'active' );
envato_market_plugins_column( 'installed' );
envato_market_plugins_column( 'install' );
}
?>
</div>
</div>

View File

@@ -0,0 +1,24 @@
<?php
/**
* Settings panel partial
*
* @package Envato_Market
* @since 1.0.0
*/
$token = envato_market()->get_option( 'token' );
$items = envato_market()->get_option( 'items', array() );
?>
<div id="settings" class="panel">
<div class="envato-market-blocks">
<?php settings_fields( envato_market()->get_slug() ); ?>
<?php Envato_Market_Admin::do_settings_sections( envato_market()->get_slug(), 2 ); ?>
</div>
<p class="submit">
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php esc_html_e( 'Save Changes', 'envato-market' ); ?>" />
<?php if ( ( '' !== $token || ! empty( $items ) ) && 10 !== has_action( 'admin_notices', array( $this, 'error_notice' ) ) ) { ?>
<a href="<?php echo esc_url( add_query_arg( array( 'authorization' => 'check' ), envato_market()->get_page_url() ) ); ?>" class="button button-secondary auth-check-button" style="margin:0 5px"><?php esc_html_e( 'Test API Connection', 'envato-market' ); ?></a>
<?php } ?>
</p>
</div>

View File

@@ -0,0 +1,50 @@
<?php
/**
* Tabs partial
*
* @package Envato_Market
* @since 1.0.0
*/
$tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : '';
$themes = envato_market()->items()->themes( 'purchased' );
$plugins = envato_market()->items()->plugins( 'purchased' );
?>
<h2 class="nav-tab-wrapper">
<?php
// Themes tab.
$theme_class = array();
if ( ! empty( $themes ) ) {
if ( empty( $tab ) ) {
$tab = 'themes';
}
if ( 'themes' === $tab ) {
$theme_class[] = 'nav-tab-active';
}
} else {
$theme_class[] = 'hidden';
}
echo '<a href="#themes" data-id="theme" class="nav-tab ' . esc_attr( implode( ' ', $theme_class ) ) . '">' . esc_html__( 'Themes', 'envato-market' ) . '</a>';
// Plugins tab.
$plugin_class = array();
if ( ! empty( $plugins ) ) {
if ( empty( $tab ) ) {
$tab = 'plugins';
}
if ( 'plugins' === $tab ) {
$plugin_class[] = 'nav-tab-active';
}
} else {
$plugin_class[] = 'hidden';
}
echo '<a href="#plugins" data-id="plugin" class="nav-tab ' . esc_attr( implode( ' ', $plugin_class ) ) . '">' . esc_html__( 'Plugins', 'envato-market' ) . '</a>';
// Settings tab.
echo '<a href="#settings" class="nav-tab ' . esc_attr( 'settings' === $tab || empty( $tab ) ? 'nav-tab-active' : '' ) . '">' . esc_html__( 'Settings', 'envato-market' ) . '</a>';
// Help tab.
echo '<a href="#help" class="nav-tab ' . esc_attr( 'help' === $tab ? 'nav-tab-active' : '' ) . '">' . esc_html__( 'Help', 'envato-market' ) . '</a>';
?>
</h2>

View File

@@ -0,0 +1,22 @@
<?php
/**
* Themes panel partial
*
* @package Envato_Market
* @since 1.0.0
*/
$themes = envato_market()->items()->themes( 'purchased' );
?>
<div id="themes" class="panel <?php echo empty( $themes ) ? 'hidden' : ''; ?>">
<div class="envato-market-blocks">
<?php
if ( ! empty( $themes ) ) {
envato_market_themes_column( 'active' );
envato_market_themes_column( 'installed' );
envato_market_themes_column( 'install' );
}
?>
</div>
</div>