Merge branch 'master' into tax-rate-auto-ordering

# Conflicts:
#	assets/css/admin.css
This commit is contained in:
Mike Jolley 2016-08-04 14:06:52 +01:00
commit c61c08f405
37 changed files with 2539 additions and 620 deletions

File diff suppressed because one or more lines are too long

View File

@ -306,7 +306,12 @@ table.wc_status_table {
#log-viewer-select {
padding: 10px 0 8px;
line-height: 180%;
line-height: 28px;
h2 {
a {
vertical-align: middle;
}
}
}
#log-viewer {

File diff suppressed because one or more lines are too long

View File

@ -547,6 +547,11 @@ html[dir="rtl"] .select2-container-multi .select2-choices li
background-color: #e4e4e4;
}
.select2-container-multi .ui-sortable .select2-search-choice {
cursor: move;
}
html[dir="rtl"] .select2-container-multi .select2-choices .select2-search-choice
{
margin: 3px 5px 3px 0;

View File

@ -146,7 +146,18 @@ jQuery( function( $ ) {
select2_args = $.extend( select2_args, getEnhancedSelectFormatString() );
$( this ).select2( select2_args ).addClass( 'enhanced' );
if( $( this ).data( 'sortable' ) === true ){
$( this ).select2( 'container' ).find( 'ul.select2-choices' ).sortable({
containment: 'parent',
start: function() { $( this ).select2( 'onSortStart' ); },
update: function() { $( this ).select2( 'onSortEnd' ); }
});
}
});
// Ajax customer search boxes
$( ':input.wc-customer-search' ).filter( ':not(.enhanced)' ).each( function() {
@ -215,6 +226,15 @@ jQuery( function( $ ) {
select2_args = $.extend( select2_args, getEnhancedSelectFormatString() );
$( this ).select2( select2_args ).addClass( 'enhanced' );
if( $( this ).data( 'sortable' ) === true ){
$( this ).select2( 'container' ).find( 'ul.select2-choices' ).sortable({
containment: 'parent',
start: function() { $( this ).select2( 'onSortStart' ); },
update: function() { $( this ).select2( 'onSortEnd' ); }
});
}
});
})

View File

@ -1 +1 @@
jQuery(function(a){function b(){var a={formatMatches:function(a){return 1===a?wc_enhanced_select_params.i18n_matches_1:wc_enhanced_select_params.i18n_matches_n.replace("%qty%",a)},formatNoMatches:function(){return wc_enhanced_select_params.i18n_no_matches},formatAjaxError:function(){return wc_enhanced_select_params.i18n_ajax_error},formatInputTooShort:function(a,b){var c=b-a.length;return 1===c?wc_enhanced_select_params.i18n_input_too_short_1:wc_enhanced_select_params.i18n_input_too_short_n.replace("%qty%",c)},formatInputTooLong:function(a,b){var c=a.length-b;return 1===c?wc_enhanced_select_params.i18n_input_too_long_1:wc_enhanced_select_params.i18n_input_too_long_n.replace("%qty%",c)},formatSelectionTooBig:function(a){return 1===a?wc_enhanced_select_params.i18n_selection_too_long_1:wc_enhanced_select_params.i18n_selection_too_long_n.replace("%qty%",a)},formatLoadMore:function(){return wc_enhanced_select_params.i18n_load_more},formatSearching:function(){return wc_enhanced_select_params.i18n_searching}};return a}a(document.body).on("wc-enhanced-select-init",function(){a(":input.wc-enhanced-select, :input.chosen_select").filter(":not(.enhanced)").each(function(){var c=a.extend({minimumResultsForSearch:10,allowClear:!!a(this).data("allow_clear"),placeholder:a(this).data("placeholder")},b());a(this).select2(c).addClass("enhanced")}),a(":input.wc-enhanced-select-nostd, :input.chosen_select_nostd").filter(":not(.enhanced)").each(function(){var c=a.extend({minimumResultsForSearch:10,allowClear:!0,placeholder:a(this).data("placeholder")},b());a(this).select2(c).addClass("enhanced")}),a(":input.wc-product-search").filter(":not(.enhanced)").each(function(){var c={allowClear:!!a(this).data("allow_clear"),placeholder:a(this).data("placeholder"),minimumInputLength:a(this).data("minimum_input_length")?a(this).data("minimum_input_length"):"3",escapeMarkup:function(a){return a},ajax:{url:wc_enhanced_select_params.ajax_url,dataType:"json",quietMillis:250,data:function(b){return{term:b,action:a(this).data("action")||"woocommerce_json_search_products_and_variations",security:wc_enhanced_select_params.search_products_nonce,exclude:a(this).data("exclude"),include:a(this).data("include"),limit:a(this).data("limit")}},results:function(b){var c=[];return b&&a.each(b,function(a,b){c.push({id:a,text:b})}),{results:c}},cache:!0}};a(this).data("multiple")===!0?(c.multiple=!0,c.initSelection=function(b,c){var d=a.parseJSON(b.attr("data-selected")),e=[];return a(b.val().split(",")).each(function(a,b){e.push({id:b,text:d[b]})}),c(e)},c.formatSelection=function(a){return'<div class="selected-option" data-id="'+a.id+'">'+a.text+"</div>"}):(c.multiple=!1,c.initSelection=function(a,b){var c={id:a.val(),text:a.attr("data-selected")};return b(c)}),c=a.extend(c,b()),a(this).select2(c).addClass("enhanced")}),a(":input.wc-customer-search").filter(":not(.enhanced)").each(function(){var c={allowClear:!!a(this).data("allow_clear"),placeholder:a(this).data("placeholder"),minimumInputLength:a(this).data("minimum_input_length")?a(this).data("minimum_input_length"):"3",escapeMarkup:function(a){return a},ajax:{url:wc_enhanced_select_params.ajax_url,dataType:"json",quietMillis:250,data:function(b){return{term:b,action:"woocommerce_json_search_customers",security:wc_enhanced_select_params.search_customers_nonce,exclude:a(this).data("exclude")}},results:function(b){var c=[];return b&&a.each(b,function(a,b){c.push({id:a,text:b})}),{results:c}},cache:!0}};a(this).data("multiple")===!0?(c.multiple=!0,c.initSelection=function(b,c){var d=a.parseJSON(b.attr("data-selected")),e=[];return a(b.val().split(",")).each(function(a,b){e.push({id:b,text:d[b]})}),c(e)},c.formatSelection=function(a){return'<div class="selected-option" data-id="'+a.id+'">'+a.text+"</div>"}):(c.multiple=!1,c.initSelection=function(a,b){var c={id:a.val(),text:a.attr("data-selected")};return b(c)}),c=a.extend(c,b()),a(this).select2(c).addClass("enhanced")})}).on("wc_backbone_modal_before_remove",function(){a(":input.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search").select2("close")}).trigger("wc-enhanced-select-init")});
jQuery(function(a){function b(){var a={formatMatches:function(a){return 1===a?wc_enhanced_select_params.i18n_matches_1:wc_enhanced_select_params.i18n_matches_n.replace("%qty%",a)},formatNoMatches:function(){return wc_enhanced_select_params.i18n_no_matches},formatAjaxError:function(){return wc_enhanced_select_params.i18n_ajax_error},formatInputTooShort:function(a,b){var c=b-a.length;return 1===c?wc_enhanced_select_params.i18n_input_too_short_1:wc_enhanced_select_params.i18n_input_too_short_n.replace("%qty%",c)},formatInputTooLong:function(a,b){var c=a.length-b;return 1===c?wc_enhanced_select_params.i18n_input_too_long_1:wc_enhanced_select_params.i18n_input_too_long_n.replace("%qty%",c)},formatSelectionTooBig:function(a){return 1===a?wc_enhanced_select_params.i18n_selection_too_long_1:wc_enhanced_select_params.i18n_selection_too_long_n.replace("%qty%",a)},formatLoadMore:function(){return wc_enhanced_select_params.i18n_load_more},formatSearching:function(){return wc_enhanced_select_params.i18n_searching}};return a}a(document.body).on("wc-enhanced-select-init",function(){a(":input.wc-enhanced-select, :input.chosen_select").filter(":not(.enhanced)").each(function(){var c=a.extend({minimumResultsForSearch:10,allowClear:!!a(this).data("allow_clear"),placeholder:a(this).data("placeholder")},b());a(this).select2(c).addClass("enhanced")}),a(":input.wc-enhanced-select-nostd, :input.chosen_select_nostd").filter(":not(.enhanced)").each(function(){var c=a.extend({minimumResultsForSearch:10,allowClear:!0,placeholder:a(this).data("placeholder")},b());a(this).select2(c).addClass("enhanced")}),a(":input.wc-product-search").filter(":not(.enhanced)").each(function(){var c={allowClear:!!a(this).data("allow_clear"),placeholder:a(this).data("placeholder"),minimumInputLength:a(this).data("minimum_input_length")?a(this).data("minimum_input_length"):"3",escapeMarkup:function(a){return a},ajax:{url:wc_enhanced_select_params.ajax_url,dataType:"json",quietMillis:250,data:function(b){return{term:b,action:a(this).data("action")||"woocommerce_json_search_products_and_variations",security:wc_enhanced_select_params.search_products_nonce,exclude:a(this).data("exclude"),include:a(this).data("include"),limit:a(this).data("limit")}},results:function(b){var c=[];return b&&a.each(b,function(a,b){c.push({id:a,text:b})}),{results:c}},cache:!0}};a(this).data("multiple")===!0?(c.multiple=!0,c.initSelection=function(b,c){var d=a.parseJSON(b.attr("data-selected")),e=[];return a(b.val().split(",")).each(function(a,b){e.push({id:b,text:d[b]})}),c(e)},c.formatSelection=function(a){return'<div class="selected-option" data-id="'+a.id+'">'+a.text+"</div>"}):(c.multiple=!1,c.initSelection=function(a,b){var c={id:a.val(),text:a.attr("data-selected")};return b(c)}),c=a.extend(c,b()),a(this).select2(c).addClass("enhanced"),a(this).data("sortable")===!0&&a(this).select2("container").find("ul.select2-choices").sortable({containment:"parent",start:function(){a(this).select2("onSortStart")},update:function(){a(this).select2("onSortEnd")}})}),a(":input.wc-customer-search").filter(":not(.enhanced)").each(function(){var c={allowClear:!!a(this).data("allow_clear"),placeholder:a(this).data("placeholder"),minimumInputLength:a(this).data("minimum_input_length")?a(this).data("minimum_input_length"):"3",escapeMarkup:function(a){return a},ajax:{url:wc_enhanced_select_params.ajax_url,dataType:"json",quietMillis:250,data:function(b){return{term:b,action:"woocommerce_json_search_customers",security:wc_enhanced_select_params.search_customers_nonce,exclude:a(this).data("exclude")}},results:function(b){var c=[];return b&&a.each(b,function(a,b){c.push({id:a,text:b})}),{results:c}},cache:!0}};a(this).data("multiple")===!0?(c.multiple=!0,c.initSelection=function(b,c){var d=a.parseJSON(b.attr("data-selected")),e=[];return a(b.val().split(",")).each(function(a,b){e.push({id:b,text:d[b]})}),c(e)},c.formatSelection=function(a){return'<div class="selected-option" data-id="'+a.id+'">'+a.text+"</div>"}):(c.multiple=!1,c.initSelection=function(a,b){var c={id:a.val(),text:a.attr("data-selected")};return b(c)}),c=a.extend(c,b()),a(this).select2(c).addClass("enhanced"),a(this).data("sortable")===!0&&a(this).select2("container").find("ul.select2-choices").sortable({containment:"parent",start:function(){a(this).select2("onSortStart")},update:function(){a(this).select2("onSortEnd")}})})}).on("wc_backbone_modal_before_remove",function(){a(":input.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search").select2("close")}).trigger("wc-enhanced-select-init")});

View File

@ -55,7 +55,7 @@ jQuery( function( $ ) {
$( 'input#createaccount' ).change( this.toggle_create_account ).change();
}
},
init_payment_methods: function() {
init_payment_methods: function( selectedPaymentMethod ) {
var $payment_methods = $( '.woocommerce-checkout' ).find( 'input[name="payment_method"]' );
// If there is one method, we can hide the radio input
@ -63,6 +63,11 @@ jQuery( function( $ ) {
$payment_methods.eq(0).hide();
}
// If there was a previously selected method, check that one.
if ( selectedPaymentMethod ) {
$( '#' + selectedPaymentMethod ).prop( 'checked', true );
}
// If there are none selected, select the first.
if ( 0 === $payment_methods.filter( ':checked' ).length ) {
$payment_methods.eq(0).prop( 'checked', true );
@ -271,6 +276,9 @@ jQuery( function( $ ) {
url: wc_checkout_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'update_order_review' ),
data: data,
success: function( data ) {
var selectedPaymentMethod = $( '.woocommerce-checkout input[name="payment_method"]:checked' ).attr( 'id' );
// Reload the page if requested
if ( 'true' === data.reload ) {
window.location.reload();
@ -321,7 +329,7 @@ jQuery( function( $ ) {
}
// Re-init methods
wc_checkout_form.init_payment_methods();
wc_checkout_form.init_payment_methods( selectedPaymentMethod );
// Fire updated_checkout e
$( document.body ).trigger( 'updated_checkout' );

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1429,7 +1429,7 @@ class WC_Product {
* @return bool
*/
public function enable_dimensions_display() {
return apply_filters( 'wc_product_enable_dimensions_display', true );
return apply_filters( 'wc_product_enable_dimensions_display', true ) && ( $this->has_dimensions() || $this->has_weight() );
}
/**
@ -1441,6 +1441,15 @@ class WC_Product {
return $this->get_dimensions() ? true : false;
}
/**
* Does a child have dimensions set?
* @since 2.7.0
* @return boolean
*/
public function child_has_dimensions() {
return false;
}
/**
* Returns the product length.
* @return string
@ -1483,6 +1492,15 @@ class WC_Product {
return $this->get_weight() ? true : false;
}
/**
* Does a child have a weight set?
* @since 2.7.0
* @return boolean
*/
public function child_has_weight() {
return false;
}
/**
* Returns formatted dimensions.
* @return string

View File

@ -205,7 +205,13 @@ class WC_Admin_Status {
$viewed_log = current( $logs );
}
include_once( dirname( __FILE__ ) . '/views/html-admin-page-status-logs.php' );
$handle = ! empty( $viewed_log ) ? self::get_log_file_handle( $viewed_log ) : '';
if ( ! empty( $_REQUEST[ 'handle' ] ) ) {
self::remove_log();
}
include_once( 'views/html-admin-page-status-logs.php' );
}
/**
@ -240,6 +246,16 @@ class WC_Admin_Status {
return $version ;
}
/**
* Return the log file handle.
*
* @param string $filename
* @return string
*/
public static function get_log_file_handle( $filename ) {
return substr( $filename, 0, strlen( $filename ) > 37 ? strlen( $filename ) - 37 : strlen( $filename ) - 4 );
}
/**
* Scan the template files.
* @param string $template_path
@ -342,4 +358,21 @@ class WC_Admin_Status {
return $update_theme_version;
}
/**
* Remove/delete the chosen file.
*/
public static function remove_log() {
if ( empty( $_REQUEST[ '_wpnonce' ] ) || ! wp_verify_nonce( $_REQUEST[ '_wpnonce' ], 'remove_log' ) ) {
wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
}
if ( ! empty( $_REQUEST[ 'handle' ] ) ) {
$logger = new WC_Logger();
$logger->remove( $_REQUEST[ 'handle' ] );
}
wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=wc-status&tab=logs' ) ) );
exit();
}
}

View File

@ -242,14 +242,14 @@ class WC_Admin_Report {
$key = is_array( $value['meta_key'] ) ? $value['meta_key'][0] . '_array' : $value['meta_key'];
if ( strtolower( $value['operator'] ) == 'in' ) {
if ( strtolower( $value['operator'] ) == 'in' || strtolower( $value['operator'] ) == 'not in' ) {
if ( is_array( $value['meta_value'] ) ) {
$value['meta_value'] = implode( "','", $value['meta_value'] );
}
if ( ! empty( $value['meta_value'] ) ) {
$where_value = "IN ('{$value['meta_value']}')";
$where_value = "{$value['operator']} ('{$value['meta_value']}')";
}
} else {
$where_value = "{$value['operator']} '{$value['meta_value']}'";
@ -289,14 +289,14 @@ class WC_Admin_Report {
foreach ( $where as $value ) {
if ( strtolower( $value['operator'] ) == 'in' ) {
if ( strtolower( $value['operator'] ) == 'in' || strtolower( $value['operator'] ) == 'not in' ) {
if ( is_array( $value['value'] ) ) {
$value['value'] = implode( "','", $value['value'] );
}
if ( ! empty( $value['value'] ) ) {
$where_value = "IN ('{$value['value']}')";
$where_value = "{$value['operator']} ('{$value['value']}')";
}
} else {
$where_value = "{$value['operator']} '{$value['value']}'";

View File

@ -11,7 +11,12 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php if ( $logs ) : ?>
<div id="log-viewer-select">
<div class="alignleft">
<h2><?php printf( __( 'Log file: %s (%s)', 'woocommerce' ), esc_html( $viewed_log ), date_i18n( get_option( 'date_format') . ' ' . get_option( 'time_format'), filemtime( WC_LOG_DIR . $viewed_log ) ) ); ?></h2>
<h2>
<?php echo esc_html( $viewed_log ); ?>
<?php if ( ! empty( $handle ) ) : ?>
<a class="page-title-action" href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'handle' => $handle ), admin_url( 'admin.php?page=wc-status&tab=logs' ) ), 'remove_log' ) ); ?>" class="button"><?php esc_html_e( 'Delete Log', 'woocommerce');?></a>
<?php endif; ?>
</h2>
</div>
<div class="alignright">
<form action="<?php echo admin_url( 'admin.php?page=wc-status&tab=logs' ); ?>" method="post">
@ -26,7 +31,7 @@ if ( ! defined( 'ABSPATH' ) ) {
<div class="clear"></div>
</div>
<div id="log-viewer">
<textarea cols="70" rows="25"><?php echo esc_textarea( file_get_contents( WC_LOG_DIR . $viewed_log ) ); ?></textarea>
<textarea cols="70" rows="40"><?php echo esc_textarea( file_get_contents( WC_LOG_DIR . $viewed_log ) ); ?></textarea>
</div>
<?php else : ?>
<div class="updated woocommerce-message inline"><p><?php _e( 'There are currently no logs to view.', 'woocommerce' ); ?></p></div>

View File

@ -0,0 +1,747 @@
<?php
/**
* REST API WC System Status controller
*
* Handles requests to the /system_status endpoint.
*
* @author WooThemes
* @category API
* @package WooCommerce/API
* @since 2.7.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* @package WooCommerce/API
* @extends WC_REST_Controller
*/
class WC_REST_System_Status_Controller extends WC_REST_Controller {
/**
* Endpoint namespace.
*
* @var string
*/
protected $namespace = 'wc/v1';
/**
* Route base.
*
* @var string
*/
protected $rest_base = 'system_status';
/**
* Register the routes for coupons.
*/
public function register_routes() {
register_rest_route( $this->namespace, '/' . $this->rest_base, array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
'args' => $this->get_collection_params(),
),
'schema' => array( $this, 'get_public_item_schema' ),
) );
}
/**
* Check whether a given request has permission to view system status.
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_Error|boolean
*/
public function get_items_permissions_check( $request ) {
if ( ! wc_rest_check_manager_permissions( 'system_status', 'read' ) ) {
return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
}
return true;
}
/**
* Get a system status info, by section.
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_Error|WP_REST_Response
*/
public function get_items( $request ) {
$schema = $this->get_item_schema();
$mappings = $this->get_item_mappings();
$response = array();
foreach ( $mappings as $section => $values ) {
settype( $values, $schema['properties'][ $section ]['type'] );
foreach ( $values as $key => $value ) {
if ( isset( $schema['properties'][ $section ]['properties'][ $key ]['type'] ) ) {
settype( $values[ $key ], $schema['properties'][ $section ]['properties'][ $key ]['type'] );
}
}
$response[ $section ] = $values;
}
return rest_ensure_response( $response );
}
/**
* Get the system status schema, conforming to JSON Schema.
*
* @return array
*/
public function get_item_schema() {
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'system_status',
'type' => 'object',
'properties' => array(
'environment' => array(
'description' => __( 'Environment', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
'properties' => array(
'home_url' => array(
'description' => __( 'Home URL', 'woocommerce' ),
'type' => 'string',
'format' => 'uri',
'context' => array( 'view', 'edit' ),
),
'site_url' => array(
'description' => __( 'Site URL', 'woocommerce' ),
'type' => 'string',
'format' => 'uri',
'context' => array( 'view', 'edit' ),
),
'wc_version' => array(
'description' => __( 'WooCommerce Version', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'log_directory' => array(
'description' => __( 'Log Directory', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'log_directory_writable' => array(
'description' => __( 'Is Log Directory Writable?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'wp_version' => array(
'description' => __( 'WordPress Version', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'wp_multisite' => array(
'description' => __( 'Is WordPress Multisite?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'wp_memory_limit' => array(
'description' => __( 'WordPress Memory Limit', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'wp_debug_mode' => array(
'description' => __( 'Is WordPress Debug Mode Active?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'wp_cron' => array(
'description' => __( 'Are WordPress Cron Jobs Enabled?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'language' => array(
'description' => __( 'WordPress Language', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'server_info' => array(
'description' => __( 'Server Info', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'php_version' => array(
'description' => __( 'PHP Version', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'php_post_max_size' => array(
'description' => __( 'PHP Post Max Size', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'php_max_execution_time' => array(
'description' => __( 'PHP Max Execution Time', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'php_max_input_vars' => array(
'description' => __( 'PHP Max Input Vars', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'curl_version' => array(
'description' => __( 'cURL Version', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'suhosin_installed' => array(
'description' => __( 'Is SUHOSIN Installed?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'max_upload_size' => array(
'description' => __( 'Max Upload Size', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'mysql_version' => array(
'description' => __( 'MySQL Version', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'default_timezone' => array(
'description' => __( 'Default Timezone', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'fsockopen_or_curl_enabled' => array(
'description' => __( 'Is fsockopen/cURL Enabled?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'soapclient_enabled' => array(
'description' => __( 'Is SoapClient Class Enabled?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'domdocument_enabled' => array(
'description' => __( 'Is DomDocument Class Enabled?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'gzip_enabled' => array(
'description' => __( 'Is GZip Enabled?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'mbstring_enabled' => array(
'description' => __( 'Is mbstring Enabled?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'remote_post_successful' => array(
'description' => __( 'Remote POST Successful?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'remote_post_response' => array(
'description' => __( 'Remote POST Response', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'remote_get_successful' => array(
'description' => __( 'Remote GET Successful?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'remote_get_response' => array(
'description' => __( 'Remote GET Response', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
),
),
'database' => array(
'description' => __( 'Database', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
'properties' => array(
'wc_database_version' => array(
'description' => __( 'WC Database Version', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'database_prefix' => array(
'description' => __( 'Database Prefix', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'maxmind_geoip_database' => array(
'description' => __( 'MaxMind GeoIP Database', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'database_tables' => array(
'description' => __( 'Database Tables', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
),
)
),
'active_plugins' => array(
'description' => __( 'Active Plugins', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
),
'theme' => array(
'description' => __( 'Theme', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
'properties' => array(
'name' => array(
'description' => __( 'Theme Name', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'version' => array(
'description' => __( 'Theme Version', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'author_url' => array(
'description' => __( 'Theme Author URL', 'woocommerce' ),
'type' => 'string',
'format' => 'uri',
'context' => array( 'view', 'edit' ),
),
'is_child_theme' => array(
'description' => __( 'Is this theme a child theme?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'has_woocommerce_support' => array(
'description' => __( 'Does the theme declare WooCommerce support?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'overrides' => array(
'description' => __( 'Template Overrides', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
),
'parent_name' => array(
'description' => __( 'Parent Theme Name', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'parent_version' => array(
'description' => __( 'Parent Theme Version', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'parent_author_url' => array(
'description' => __( 'Parent Theme Author URL', 'woocommerce' ),
'type' => 'string',
'format' => 'uri',
'context' => array( 'view', 'edit' ),
),
)
),
'settings' => array(
'description' => __( 'Settings', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
'properties' => array(
'api_enabled' => array(
'description' => __( 'REST API Enabled?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'force_ssl' => array(
'description' => __( 'SSL Forced?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'currency' => array(
'description' => __( 'Currency', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'currency_symbol' => array(
'description' => __( 'Currency Symbol', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'currency_position' => array(
'description' => __( 'Currency Position', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'thousand_separator' => array(
'description' => __( 'Thousand Separator', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'decimal_separator' => array(
'description' => __( 'Decimal Separator', 'woocommerce' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
),
'number_of_decimals' => array(
'description' => __( 'Number of Decimals', 'woocommerce' ),
'type' => 'integer',
'context' => array( 'view', 'edit' ),
),
'geolocation_enabled' => array(
'description' => __( 'Geolocation Enabled?', 'woocommerce' ),
'type' => 'boolean',
'context' => array( 'view', 'edit' ),
),
'taxonomies' => array(
'description' => __( 'Taxonomy Terms for Product/Order Statuses', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
),
)
),
'pages' => array(
'description' => __( 'WooCommerce Pages', 'woocommerce' ),
'type' => 'array',
'context' => array( 'view', 'edit' ),
),
)
);
return $this->add_additional_fields_schema( $schema );
}
/**
* Return an array of sections and the data associated with each.
*
* @return array
*/
public function get_item_mappings() {
return array(
'environment' => $this->get_environment_info(),
'database' => $this->get_database_info(),
'active_plugins' => $this->get_active_plugins(),
'theme' => $this->get_theme_info(),
'settings' => $this->get_settings(),
'pages' => $this->get_pages(),
);
}
/**
* Get array of environment information. Includes thing like software
* versions, and various server settings.
*
* @return array
*/
public function get_environment_info() {
global $wpdb;
// Figure out cURL version, if installed.
$curl_version = '';
if ( function_exists( 'curl_version' ) ) {
$curl_version = curl_version();
$curl_version = $curl_version['version'] . ', ' . $curl_version['ssl_version'];
}
// WP memory limit
$wp_memory_limit = wc_let_to_num( WP_MEMORY_LIMIT );
if ( function_exists( 'memory_get_usage' ) ) {
$wp_memory_limit = max( $wp_memory_limit, wc_let_to_num( @ini_get( 'memory_limit' ) ) );
}
// Test POST requests
$post_response = wp_safe_remote_post( 'https://www.paypal.com/cgi-bin/webscr', array(
'timeout' => 60,
'user-agent' => 'WooCommerce/' . WC()->version,
'httpversion' => '1.1',
'body' => array(
'cmd' => '_notify-validate'
)
) );
$post_response_successful = false;
if ( ! is_wp_error( $post_response ) && $post_response['response']['code'] >= 200 && $post_response['response']['code'] < 300 ) {
$post_response_successful = true;
}
// Test GET requests
$get_response = wp_safe_remote_get( 'https://woocommerce.com/wc-api/product-key-api?request=ping&network=' . ( is_multisite() ? '1' : '0' ) );
$get_response_successful = false;
if ( ! is_wp_error( $post_response ) && $post_response['response']['code'] >= 200 && $post_response['response']['code'] < 300 ) {
$get_response_successful = true;
}
// Return all environment info. Described by JSON Schema.
return array(
'home_url' => get_option( 'home' ),
'site_url' => get_option( 'siteurl' ),
'version' => WC()->version,
'log_directory' => WC_LOG_DIR,
'log_directory_writable' => ( @fopen( WC_LOG_DIR . 'test-log.log', 'a' ) ? true : false ),
'wp_version' => get_bloginfo('version'),
'wp_multisite' => is_multisite(),
'wp_memory_limit' => $wp_memory_limit,
'wp_debug_mode' => ( defined( 'WP_DEBUG' ) && WP_DEBUG ),
'wp_cron' => ! ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ),
'language' => get_locale(),
'server_info' => $_SERVER['SERVER_SOFTWARE'],
'php_version' => phpversion(),
'php_post_max_size' => wc_let_to_num( ini_get( 'post_max_size' ) ),
'php_max_execution_time' => ini_get( 'max_execution_time' ),
'php_max_input_vars' => ini_get( 'max_input_vars' ),
'curl_version' => $curl_version,
'suhosin_installed' => extension_loaded( 'suhosin' ),
'max_upload_size' => wp_max_upload_size(),
'mysql_version' => ( ! empty( $wpdb->is_mysql ) ? $wpdb->db_version() : '' ),
'default_timezone' => date_default_timezone_get(),
'fsockopen_or_curl_enabled' => ( function_exists( 'fsockopen' ) || function_exists( 'curl_init' ) ),
'soapclient_enabled' => class_exists( 'SoapClient' ),
'domdocument_enabled' => class_exists( 'DOMDocument' ),
'gzip_enabled' => is_callable( 'gzopen' ),
'mbstring_enabled' => extension_loaded( 'mbstring' ),
'remote_post_successful' => $post_response_successful,
'remote_post_response' => ( is_wp_error( $post_response ) ? $post_response->get_error_message() : $post_response['response']['code'] ),
'remote_get_successful' => $get_response_successful,
'remote_get_response' => ( is_wp_error( $get_response ) ? $get_response->get_error_message() : $get_response['response']['code'] ),
);
}
/**
* Get array of database information. Version, prefix, and table existence.
*
* @return array
*/
public function get_database_info() {
global $wpdb;
// WC Core tables to check existence of
$tables = array(
'woocommerce_sessions',
'woocommerce_api_keys',
'woocommerce_attribute_taxonomies',
'woocommerce_downloadable_product_permissions',
'woocommerce_order_items',
'woocommerce_order_itemmeta',
'woocommerce_tax_rates',
'woocommerce_tax_rate_locations',
'woocommerce_shipping_zones',
'woocommerce_shipping_zone_locations',
'woocommerce_shipping_zone_methods',
'woocommerce_payment_tokens',
'woocommerce_payment_tokenmeta',
);
if ( get_option( 'db_version' ) < 34370 ) {
$tables[] = 'woocommerce_termmeta';
}
$table_exists = array();
foreach ( $tables as $table ) {
$table_exists[ $table ] = ( $wpdb->get_var( $wpdb->prepare( "SHOW TABLES LIKE %s;", $wpdb->prefix . $table ) ) === $wpdb->prefix . $table );
}
// Return all database info. Described by JSON Schema.
return array(
'wc_database_version' => get_option( 'woocommerce_db_version' ),
'database_prefix' => $wpdb->prefix,
'maxmind_geoip_database' => WC_Geolocation::get_local_database_path(),
'database_tables' => $table_exists,
);
}
/**
* Get a list of plugins active on the site.
*
* @return array
*/
public function get_active_plugins() {
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
// Get both site plugins and network plugins
$active_plugins = (array) get_option( 'active_plugins', array() );
if ( is_multisite() ) {
$network_activated_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) );
$active_plugins = array_merge( $active_plugins, $network_activated_plugins );
}
$active_plugins_data = array();
foreach ( $active_plugins as $plugin ) {
$data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
// convert plugin data to json response format.
$active_plugins_data[] = array(
'name' => $data['Name'],
'version' => $data['Version'],
'url' => $data['PluginURI'],
'author_name' => $data['AuthorName'],
'author_url' => esc_url_raw( $data['AuthorURI'] ),
);
}
return $active_plugins_data;
}
/**
* Get info on the current active theme, info on parent theme (if presnet)
* and a list of template overrides.
*
* @return array
*/
public function get_theme_info() {
$active_theme = wp_get_theme();
// Get parent theme info if this theme is a child theme, otherwise
// pass empty info in the response.
if ( is_child_theme() ) {
$parent_theme = wp_get_theme( $active_theme->Template );
$parent_theme_info = array(
'parent_name' => $parent_theme->Name,
'parentversion' => $parent_theme->Version,
'parent_author_url' => $parent_theme->{'Author URI'},
);
} else {
$parent_theme_info = array( 'parent_theme_name' => '', 'parent_theme_version' => '', 'parent_theme_author_url' => '' );
}
/**
* Scan the theme directory for all WC templates to see if our theme
* overrides any of them.
*/
$override_files = array();
$scan_files = WC_Admin_Status::scan_template_files( WC()->plugin_path() . '/templates/' );
foreach ( $scan_files as $file ) {
if ( file_exists( get_stylesheet_directory() . '/' . $file ) ) {
$theme_file = get_stylesheet_directory() . '/' . $file;
} elseif ( file_exists( get_stylesheet_directory() . '/woocommerce/' . $file ) ) {
$theme_file = get_stylesheet_directory() . '/woocommerce/' . $file;
} elseif ( file_exists( get_template_directory() . '/' . $file ) ) {
$theme_file = get_template_directory() . '/' . $file;
} elseif ( file_exists( get_template_directory() . '/woocommerce/' . $file ) ) {
$theme_file = get_template_directory() . '/woocommerce/' . $file;
} else {
$theme_file = false;
}
if ( ! empty( $theme_file ) ) {
$override_files[] = str_replace( WP_CONTENT_DIR . '/themes/', '', $theme_file );
}
}
$active_theme_info = array(
'name' => $active_theme->Name,
'version' => $active_theme->Version,
'author_url' => esc_url_raw( $active_theme->{'Author URI'} ),
'is_child_theme' => is_child_theme(),
'has_woocommerce_support' => ( current_theme_supports( 'woocommerce' ) || in_array( $active_theme->template, wc_get_core_supported_themes() ) ),
'overrides' => $override_files,
);
return array_merge( $active_theme_info, $parent_theme_info );
}
/**
* Get some setting values for the site that are useful for debugging
* purposes. For full settings access, use the settings api.
*
* @return array
*/
public function get_settings() {
// Get a list of terms used for product/order taxonomies
$term_response = array();
$terms = get_terms( 'product_type', array( 'hide_empty' => 0 ) );
foreach ( $terms as $term ) {
$term_response[ $term->slug ] = strtolower( $term->name );
}
// Return array of useful settings for debugging.
return array(
'api_enabled' => 'yes' === get_option( 'woocommerce_api_enabled' ),
'force_ssl' => 'yes' === get_option( 'woocommerce_force_ssl_checkout' ),
'currency' => get_woocommerce_currency(),
'currency_symbol' => get_woocommerce_currency_symbol(),
'currency_position' => get_option( 'woocommerce_currency_pos' ),
'thousand_separator' => wc_get_price_thousand_separator(),
'decimal_separator' => wc_get_price_decimal_separator(),
'number_of_decimals' => wc_get_price_decimals(),
'geolocation_enabled' => in_array( get_option( 'woocommerce_default_customer_address' ), array( 'geolocation_ajax', 'geolocation' ) ),
'taxonomies' => $term_response,
);
}
/**
* Returns a mini-report on WC pages and if they are configured correctly:
* Present, visible, and including the correct shortcode.
*
* @return array
*/
public function get_pages() {
// WC pages to check against
$check_pages = array(
_x( 'Shop Base', 'Page setting', 'woocommerce' ) => array(
'option' => 'woocommerce_shop_page_id',
'shortcode' => '',
),
_x( 'Cart', 'Page setting', 'woocommerce' ) => array(
'option' => 'woocommerce_cart_page_id',
'shortcode' => '[' . apply_filters( 'woocommerce_cart_shortcode_tag', 'woocommerce_cart' ) . ']',
),
_x( 'Checkout', 'Page setting', 'woocommerce' ) => array(
'option' => 'woocommerce_checkout_page_id',
'shortcode' => '[' . apply_filters( 'woocommerce_checkout_shortcode_tag', 'woocommerce_checkout' ) . ']',
),
_x( 'My Account', 'Page setting', 'woocommerce' ) => array(
'option' => 'woocommerce_myaccount_page_id',
'shortcode' => '[' . apply_filters( 'woocommerce_my_account_shortcode_tag', 'woocommerce_my_account' ) . ']',
),
);
$pages_output = array();
foreach ( $check_pages as $page_name => $values ) {
$errors = array();
$page_id = get_option( $values['option'] );
$page_set = $page_exists = $page_visible = false;
$shortcode_present = $shortcode_required = false;
// Page checks
if ( $page_id ) {
$page_set = true;
}
if ( get_post( $page_id ) ) {
$page_exists = true;
}
if ( 'publish' === get_post_status( $page_id ) ) {
$page_visible = true;
}
// Shortcode checks
if ( $values['shortcode'] && get_post( $page_id ) ) {
$shortcode_required = true;
$page = get_post( $page_id );
if ( strstr( $page->post_content, $values['shortcode'] ) ) {
$shortcode_present = true;
}
}
// Wrap up our findings into an output array
$pages_output[] = array(
'page_name' => $page_name,
'page_id' => $page_id,
'page_set' => $page_set,
'page_exists' => $page_exists,
'page_visible' => $page_visible,
'shortcode_required' => $shortcode_required,
'shortcode_present' => $shortcode_present,
);
}
return $pages_output;
}
/**
* Get any query params needed.
*
* @return array
*/
public function get_collection_params() {
return array(
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
);
}
}

View File

@ -167,6 +167,7 @@ class WC_API extends WC_Legacy_API {
include_once( dirname( __FILE__ ) . '/api/class-wc-rest-taxes-controller.php' );
include_once( dirname( __FILE__ ) . '/api/class-wc-rest-webhook-deliveries.php' );
include_once( dirname( __FILE__ ) . '/api/class-wc-rest-webhooks-controller.php' );
include_once( dirname( __FILE__ ) . '/api/class-wc-rest-system-status-controller.php' );
}
/**
@ -200,6 +201,7 @@ class WC_API extends WC_Legacy_API {
'WC_REST_Taxes_Controller',
'WC_REST_Webhook_Deliveries_Controller',
'WC_REST_Webhooks_Controller',
'WC_REST_System_Status_Controller',
);
foreach ( $controllers as $controller ) {

View File

@ -211,11 +211,6 @@ class WC_Form_Handler {
$user->user_email = $account_email;
}
if ( ! empty( $pass1 ) && ! wp_check_password( $pass_cur, $current_user->user_pass, $current_user->ID ) ) {
wc_add_notice( __( 'Your current password is incorrect.', 'woocommerce' ), 'error' );
$save_pass = false;
}
if ( ! empty( $pass_cur ) && empty( $pass1 ) && empty( $pass2 ) ) {
wc_add_notice( __( 'Please fill out all password fields.', 'woocommerce' ), 'error' );
$save_pass = false;
@ -228,6 +223,9 @@ class WC_Form_Handler {
} elseif ( ( ! empty( $pass1 ) || ! empty( $pass2 ) ) && $pass1 !== $pass2 ) {
wc_add_notice( __( 'New passwords do not match.', 'woocommerce' ), 'error' );
$save_pass = false;
} elseif ( ! empty( $pass1 ) && ! wp_check_password( $pass_cur, $current_user->user_pass, $current_user->ID ) ) {
wc_add_notice( __( 'Your current password is incorrect.', 'woocommerce' ), 'error' );
$save_pass = false;
}
if ( $pass1 && $save_pass ) {
@ -873,9 +871,12 @@ class WC_Form_Handler {
if ( ! empty( $_POST['login'] ) && wp_verify_nonce( $nonce_value, 'woocommerce-login' ) ) {
try {
$creds = array();
$username = trim( $_POST['username'] );
$creds = array(
'user_password' => $_POST['password'],
'remember' => isset( $_POST['rememberme'] ),
);
$username = trim( $_POST['username'] );
$validation_error = new WP_Error();
$validation_error = apply_filters( 'woocommerce_process_login_errors', $validation_error, $_POST['username'], $_POST['password'] );
@ -904,10 +905,17 @@ class WC_Form_Handler {
$creds['user_login'] = $username;
}
$creds['user_password'] = $_POST['password'];
$creds['remember'] = isset( $_POST['rememberme'] );
$secure_cookie = is_ssl() ? true : false;
$user = wp_signon( apply_filters( 'woocommerce_login_credentials', $creds ), $secure_cookie );
// On multisite, ensure user exists on current site, if not add them before allowing login.
if ( is_multisite() ) {
$user_data = get_user_by( 'login', $username );
if ( $user_data && ! is_user_member_of_blog( $user_data->ID, get_current_blog_id() ) ) {
add_user_to_blog( get_current_blog_id(), $user_data->ID, 'customer' );
}
}
// Perform the login
$user = wp_signon( apply_filters( 'woocommerce_login_credentials', $creds ), is_ssl() );
if ( is_wp_error( $user ) ) {
$message = $user->get_error_message();

View File

@ -72,6 +72,9 @@ class WC_Install {
'wc_update_260_refunds',
'wc_update_260_db_version',
),
'2.7.0' => array(
'wc_update_270_webhooks',
),
);
/** @var object Background update class */

View File

@ -124,4 +124,29 @@ class WC_Logger {
return $result;
}
/**
* Remove/delete the chosen file.
*
* @param string $handle
*
* @return bool
*/
public function remove( $handle ) {
$removed = false;
$file = wc_get_log_file_path( $handle );
if ( is_file( $file ) && is_writable( $file ) ) {
// Close first to be certain no processes keep it alive after it is unlinked.
$this->close( $handle );
$removed = unlink( $file );
} elseif ( is_file( trailingslashit( WC_LOG_DIR ) . $handle . '.log' ) && is_writable( trailingslashit( WC_LOG_DIR ) . $handle . '.log' ) ) {
$this->close( $handle );
$removed = unlink( trailingslashit( WC_LOG_DIR ) . $handle . '.log' );
}
do_action( 'woocommerce_log_remove', $handle, $removed );
return $removed;
}
}

View File

@ -610,7 +610,7 @@ class WC_Product_Variable extends WC_Product {
'price_html' => apply_filters( 'woocommerce_show_variation_price', $variation->get_price() === "" || $this->get_variation_price( 'min' ) !== $this->get_variation_price( 'max' ), $this, $variation ) ? '<span class="price">' . $variation->get_price_html() . '</span>' : '',
'availability_html' => $availability_html,
'sku' => $variation->get_sku(),
'weight' => $variation->get_weight() . ' ' . esc_attr( get_option('woocommerce_weight_unit' ) ),
'weight' => $variation->get_weight() ? $variation->get_weight() . ' ' . esc_attr( get_option('woocommerce_weight_unit' ) ) : '',
'dimensions' => $variation->get_dimensions(),
'min_qty' => 1,
'max_qty' => $variation->backorders_allowed() ? '' : $variation->get_stock_quantity(),
@ -723,6 +723,33 @@ class WC_Product_Variable extends WC_Product {
}
}
/**
* Does a child have a weight set?
* @since 2.7.0
* @return boolean
*/
public function child_has_weight() {
return (bool) get_post_meta( $this->id, '_child_has_weight', true );
}
/**
* Does a child have dimensions set?
* @since 2.7.0
* @return boolean
*/
public function child_has_dimensions() {
return (bool) get_post_meta( $this->id, '_child_has_dimensions', true );
}
/**
* Returns whether or not we are showing dimensions on the product page.
*
* @return bool
*/
public function enable_dimensions_display() {
return apply_filters( 'wc_product_enable_dimensions_display', true ) && ( $this->has_dimensions() || $this->has_weight() || $this->child_has_weight() || $this->child_has_dimensions() );
}
/**
* Sync the variable product with it's children.
*/
@ -740,6 +767,8 @@ class WC_Product_Variable extends WC_Product {
// No published variations - product won't be purchasable.
if ( ! $children ) {
update_post_meta( $product_id, '_price', '' );
delete_post_meta( $product_id, '_child_has_weight' );
delete_post_meta( $product_id, '_child_has_dimensions' );
delete_transient( 'wc_products_onsale' );
if ( is_admin() && 'publish' === get_post_status( $product_id ) ) {
@ -826,6 +855,22 @@ class WC_Product_Variable extends WC_Product {
add_post_meta( $product_id, '_price', $max_price, false );
delete_transient( 'wc_products_onsale' );
// Sync weights
foreach ( $children as $child_id ) {
if ( get_post_meta( $child_id, '_weight', true ) ) {
update_post_meta( $product_id, '_child_has_weight', true );
break;
}
}
// Sync dimensions
foreach ( $children as $child_id ) {
if ( get_post_meta( $child_id, '_height', true ) || get_post_meta( $child_id, '_width', true ) || get_post_meta( $child_id, '_length', true ) ) {
update_post_meta( $product_id, '_child_has_dimensions', true );
break;
}
}
// Sync attributes
self::sync_attributes( $product_id, $children );

View File

@ -331,7 +331,14 @@ class WC_Shipping {
}
// Check if we need to recalculate shipping for this package
$package_hash = 'wc_ship_' . md5( json_encode( $package ) . WC_Cache_Helper::get_transient_version( 'shipping' ) );
$package_to_hash = $package;
// Remove data objects so hashes are consistent
foreach ( $package_to_hash['contents'] as $item_id => $item ) {
unset( $package_to_hash['contents'][ $item_id ]['data'] );
}
$package_hash = 'wc_ship_' . md5( json_encode( $package_to_hash ) . WC_Cache_Helper::get_transient_version( 'shipping' ) );
$status_options = get_option( 'woocommerce_status_options', array() );
$session_key = 'shipping_for_package_' . $package_key;
$stored_rates = WC()->session->get( $session_key );

View File

@ -270,6 +270,10 @@ class WC_Webhook {
break;
case 'product':
// bulk and quick edit action hooks return a product object instead of an ID
if ( 'updated' === $event && is_a( $resource_id, 'WC_Product' ) ) {
$resource_id = $resource_id->get_id();
}
$payload = WC()->api->WC_API_Products->get_product( $resource_id );
break;
@ -581,6 +585,8 @@ class WC_Webhook {
'product.updated' => array(
'woocommerce_process_product_meta',
'woocommerce_api_edit_product',
'woocommerce_product_quick_edit_save',
'woocommerce_product_bulk_edit_save',
),
'product.deleted' => array(
'wp_trash_post',

View File

@ -668,6 +668,9 @@ function wc_format_postcode( $postcode, $country ) {
case 'JP' :
$postcode = trim( substr_replace( $postcode, '-', 3, 0 ) );
break;
case 'PL' :
$postcode = trim( substr_replace( $postcode, '-', -3, 0 ) );
break;
case 'PT' :
$postcode = trim( substr_replace( $postcode, '-', 4, 0 ) );
break;

View File

@ -308,6 +308,7 @@ function wc_rest_check_manager_permissions( $object, $context = 'read' ) {
$objects = array(
'reports' => 'view_woocommerce_reports',
'settings' => 'manage_woocommerce',
'system_status' => 'manage_woocommerce',
'attributes' => 'manage_product_terms',
);

View File

@ -344,23 +344,31 @@ function wc_product_post_class( $classes, $class = '', $post_id = '' ) {
* @param array $exclude Keys to exclude.
* @param string $current_key Current key we are outputting.
*/
function wc_query_string_form_fields( $values = null, $exclude = array(), $current_key = '' ) {
function wc_query_string_form_fields( $values = null, $exclude = array(), $current_key = '', $return = false ) {
if ( is_null( $values ) ) {
$values = $_GET;
}
$html = '';
foreach ( $values as $key => $value ) {
if ( in_array( $key, $exclude ) ) {
if ( in_array( $key, $exclude, true ) ) {
continue;
}
if ( $current_key ) {
$key = $current_key . '[' . $key . ']';
}
if ( is_array( $value ) ) {
wc_query_string_form_fields( $value, $exclude, $key );
$html .= wc_query_string_form_fields( $value, $exclude, $key, true );
} else {
echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '" />';
$html .= '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '" />';
}
}
if ( $return ) {
return $html;
} else {
echo $html;
}
}
/** Template pages ********************************************************/
@ -1141,7 +1149,7 @@ if ( ! function_exists( 'woocommerce_default_product_tabs' ) ) {
}
// Additional information tab - shows attributes
if ( $product && ( $product->has_attributes() || ( $product->enable_dimensions_display() && ( $product->has_dimensions() || $product->has_weight() ) ) ) ) {
if ( $product && ( $product->has_attributes() || $product->enable_dimensions_display() ) ) {
$tabs['additional_information'] = array(
'title' => __( 'Additional Information', 'woocommerce' ),
'priority' => 20,
@ -1750,8 +1758,11 @@ if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) {
if ( $thumbnail_id ) {
$image = wp_get_attachment_image_src( $thumbnail_id, $small_thumbnail_size );
$image = $image[0];
$image_srcset = function_exists( 'wp_get_attachment_image_srcset' ) ? wp_get_attachment_image_srcset( $thumbnail_id, $small_thumbnail_size ) : false;
$image_sizes = function_exists( 'wp_get_attachment_image_sizes' ) ? wp_get_attachment_image_sizes( $thumbnail_id, $small_thumbnail_size ) : false;
} else {
$image = wc_placeholder_img_src();
$image_srcset = $image_sizes = false;
}
if ( $image ) {
@ -1759,10 +1770,15 @@ if ( ! function_exists( 'woocommerce_subcategory_thumbnail' ) ) {
// Ref: https://core.trac.wordpress.org/ticket/23605
$image = str_replace( ' ', '%20', $image );
// Add responsive image markup if available
if ( $image_srcset && $image_sizes ) {
echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" srcset="' . esc_attr( $image_srcset ) . '" sizes="' . esc_attr( $image_sizes ) . '" />';
} else {
echo '<img src="' . esc_url( $image ) . '" alt="' . esc_attr( $category->name ) . '" width="' . esc_attr( $dimensions['width'] ) . '" height="' . esc_attr( $dimensions['height'] ) . '" />';
}
}
}
}
if ( ! function_exists( 'woocommerce_order_details_table' ) ) {
@ -2037,11 +2053,19 @@ if ( ! function_exists( 'get_product_search_form' ) ) {
* @return string
*/
function get_product_search_form( $echo = true ) {
global $product_search_form_index;
ob_start();
if ( empty( $product_search_form_index ) ) {
$product_search_form_index = 0;
}
do_action( 'pre_get_product_search_form' );
wc_get_template( 'product-searchform.php' );
wc_get_template( 'product-searchform.php', array(
'index' => $product_search_form_index++,
) );
$form = apply_filters( 'get_product_search_form', ob_get_clean() );

View File

@ -970,3 +970,20 @@ function wc_update_260_refunds() {
function wc_update_260_db_version() {
WC_Install::update_db_version( '2.6.0' );
}
function wc_update_270_webhooks() {
/**
* Make sure product.update webhooks get the woocommerce_product_quick_edit_save
* and woocommerce_product_bulk_edit_save hooks.
*/
$product_update_webhooks = get_posts( array(
'posts_per_page' => -1,
'post_type' => 'shop_webhook',
'meta_key' => '_topic',
'meta_value' => 'product.updated'
) );
foreach ( $product_update_webhooks as $product_update_webhook ) {
$webhook = new WC_Webhook( $product_update_webhook->ID );
$webhook->set_topic( 'product.updated' );
}
}

View File

@ -68,45 +68,6 @@ class WC_Widget_Price_Filter extends WC_Widget {
wp_enqueue_script( 'wc-price-slider' );
// Remember current filters/search
$fields = '';
if ( get_search_query() ) {
$fields .= '<input type="hidden" name="s" value="' . get_search_query() . '" />';
}
if ( ! empty( $_GET['post_type'] ) ) {
$fields .= '<input type="hidden" name="post_type" value="' . esc_attr( $_GET['post_type'] ) . '" />';
}
if ( ! empty ( $_GET['product_cat'] ) ) {
$fields .= '<input type="hidden" name="product_cat" value="' . esc_attr( $_GET['product_cat'] ) . '" />';
}
if ( ! empty( $_GET['product_tag'] ) ) {
$fields .= '<input type="hidden" name="product_tag" value="' . esc_attr( $_GET['product_tag'] ) . '" />';
}
if ( ! empty( $_GET['orderby'] ) ) {
$fields .= '<input type="hidden" name="orderby" value="' . esc_attr( $_GET['orderby'] ) . '" />';
}
if ( ! empty( $_GET['min_rating'] ) ) {
$fields .= '<input type="hidden" name="min_rating" value="' . esc_attr( $_GET['min_rating'] ) . '" />';
}
if ( $_chosen_attributes = WC_Query::get_layered_nav_chosen_attributes() ) {
foreach ( $_chosen_attributes as $attribute => $data ) {
$taxonomy_filter = 'filter_' . str_replace( 'pa_', '', $attribute );
$fields .= '<input type="hidden" name="' . esc_attr( $taxonomy_filter ) . '" value="' . esc_attr( implode( ',', $data['terms'] ) ) . '" />';
if ( 'or' == $data['query_type'] ) {
$fields .= '<input type="hidden" name="' . esc_attr( str_replace( 'pa_', 'query_type_', $attribute ) ) . '" value="or" />';
}
}
}
// Find min and max price in current result set
$prices = $this->get_filtered_price();
$min = floor( $prices->min_price );
@ -152,7 +113,7 @@ class WC_Widget_Price_Filter extends WC_Widget {
<div class="price_label" style="display:none;">
' . __( 'Price:', 'woocommerce' ) . ' <span class="from"></span> &mdash; <span class="to"></span>
</div>
' . $fields . '
' . wc_query_string_form_fields( null, array( 'min_price', 'max_price' ), '', true ) . '
<div class="clear"></div>
</div>
</div>

View File

@ -1,5 +1,5 @@
=== WooCommerce ===
Contributors: automattic, mikejolley, jameskoster, claudiosanches, jshreve, coderkevin, woothemes, BFTrick
Contributors: automattic, mikejolley, jameskoster, claudiosanches, jshreve, coderkevin, woothemes, BFTrick, iCaleb
Tags: ecommerce, e-commerce, store, sales, sell, shop, cart, checkout, downloadable, downloads, paypal, storefront
Requires at least: 4.4
Tested up to: 4.5
@ -164,6 +164,8 @@ Yes you can! Join in on our [GitHub repository](http://github.com/woothemes/wooc
* Improved handling of shop page rewrite rules to allow subpages.
* Redirect to login after password reset.
* When using authorizations in PayPal standard, automatically capture funds when the order goes processing/completed.
* On multisite, when a user logs into a store with an account on a site, but not the current site, rather than error, add the user to the current site as a customer.
* Show variable weights/dimensions even when parent values are not set.
[See changelog for all versions](https://raw.githubusercontent.com/woothemes/woocommerce/master/CHANGELOG.txt).

View File

@ -16,16 +16,14 @@
* @version 2.5.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<form role="search" method="get" class="woocommerce-product-search" action="<?php echo esc_url( home_url( '/' ) ); ?>">
<label class="screen-reader-text" for="woocommerce-product-search-field"><?php _e( 'Search for:', 'woocommerce' ); ?></label>
<input type="search" id="woocommerce-product-search-field" class="search-field" placeholder="<?php echo esc_attr_x( 'Search Products&hellip;', 'placeholder', 'woocommerce' ); ?>" value="<?php echo get_search_query(); ?>" name="s" title="<?php echo esc_attr_x( 'Search for:', 'label', 'woocommerce' ); ?>" />
<label class="screen-reader-text" for="woocommerce-product-search-field-<?php echo isset( $index ) ? absint( $index ) : 0; ?>"><?php _e( 'Search for:', 'woocommerce' ); ?></label>
<input type="search" id="woocommerce-product-search-field-<?php echo isset( $index ) ? absint( $index ) : 0; ?>" class="search-field" placeholder="<?php echo esc_attr_x( 'Search Products&hellip;', 'placeholder', 'woocommerce' ); ?>" value="<?php echo get_search_query(); ?>" name="s" title="<?php echo esc_attr_x( 'Search for:', 'label', 'woocommerce' ); ?>" />
<input type="submit" value="<?php echo esc_attr_x( 'Search', 'submit button', 'woocommerce' ); ?>" />
<input type="hidden" name="post_type" value="product" />
</form>

View File

@ -33,17 +33,17 @@ ob_start();
<?php if ( $product->enable_dimensions_display() ) : ?>
<?php if ( $product->has_weight() ) : $has_row = true; ?>
<?php if ( $product->has_weight() || get_post_meta( $product->id, '_child_has_weight', true ) ) : $has_row = true; ?>
<tr class="<?php if ( ( $alt = $alt * -1 ) === 1 ) echo 'alt'; ?>">
<th><?php _e( 'Weight', 'woocommerce' ) ?></th>
<td class="product_weight"><?php echo wc_format_localized_decimal( $product->get_weight() ) . ' ' . esc_attr( get_option( 'woocommerce_weight_unit' ) ); ?></td>
<td class="product_weight"><?php echo $product->get_weight() ? wc_format_localized_decimal( $product->get_weight() ) . ' ' . esc_attr( get_option( 'woocommerce_weight_unit' ) ) : __( 'N/A', 'woocommerce' ); ?></td>
</tr>
<?php endif; ?>
<?php if ( $product->has_dimensions() ) : $has_row = true; ?>
<?php if ( $product->has_dimensions() || get_post_meta( $product->id, '_child_has_dimensions', true ) ) : $has_row = true; ?>
<tr class="<?php if ( ( $alt = $alt * -1 ) === 1 ) echo 'alt'; ?>">
<th><?php _e( 'Dimensions', 'woocommerce' ) ?></th>
<td class="product_dimensions"><?php echo $product->get_dimensions(); ?></td>
<td class="product_dimensions"><?php echo $product->get_dimensions() ? $product->get_dimensions() : __( 'N/A', 'woocommerce' ); ?></td>
</tr>
<?php endif; ?>

View File

@ -0,0 +1,189 @@
<?php
/**
* System Status REST Tests
* @package WooCommerce\Tests\API
* @since 2.7
*/
class WC_Tests_REST_System_Status extends WC_REST_Unit_Test_Case {
/**
* Setup our test server.
*/
public function setUp() {
parent::setUp();
$this->endpoint = new WC_REST_System_Status_Controller();
$this->user = $this->factory->user->create( array(
'role' => 'administrator',
) );
}
/**
* Test route registration.
*/
public function test_register_routes() {
$routes = $this->server->get_routes();
$this->assertArrayHasKey( '/wc/v1/system_status', $routes );
}
/**
* Test to make sure system status cannot be accessed without valid creds
*
* @since 2.7.0
*/
public function test_get_system_status_info_without_permission() {
wp_set_current_user( 0 );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/system_status' ) );
$this->assertEquals( 401, $response->get_status() );
}
/**
* Test to make sure root properties are present.
* (environment, theme, database, etc).
*
* @since 2.7.0
*/
public function test_get_system_status_info_returns_root_properties() {
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/system_status' ) );
$data = $response->get_data();
$this->assertArrayHasKey( 'environment', $data );
$this->assertArrayHasKey( 'database', $data );
$this->assertArrayHasKey( 'active_plugins', $data );
$this->assertArrayHasKey( 'theme', $data );
$this->assertArrayHasKey( 'settings', $data );
$this->assertArrayHasKey( 'pages', $data );
}
/**
* Test to make sure environment response is correct.
*
* @since 2.7.0
*/
public function test_get_system_status_info_environment() {
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/system_status' ) );
$data = $response->get_data();
$environment = $data['environment'];
// Make sure all expected data is present
$this->assertEquals( 30, count( $environment ) );
// Test some responses to make sure they match up
$this->assertEquals( get_option( 'home' ), $environment['home_url'] );
$this->assertEquals( get_option( 'siteurl' ), $environment['site_url'] );
$this->assertEquals( WC()->version, $environment['version'] );
}
/**
* Test to make sure database response is correct.
*
* @since 2.7.0
*/
public function test_get_system_status_info_database() {
global $wpdb;
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/system_status' ) );
$data = $response->get_data();
$database = $data['database'];
$this->assertEquals( get_option( 'woocommerce_db_version' ), $database['wc_database_version'] );
$this->assertEquals( $wpdb->prefix, $database['database_prefix'] );
$this->assertEquals( WC_Geolocation::get_local_database_path(), $database['maxmind_geoip_database'] );
$this->assertArrayHasKey( 'woocommerce_payment_tokens', $database['database_tables'] );
}
/**
* Test to make sure active plugins response is correct.
*
* @since 2.7.0
*/
public function test_get_system_status_info_active_plugins() {
wp_set_current_user( $this->user );
$actual_plugins = array( 'hello.php' );
update_option( 'active_plugins', $actual_plugins );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/system_status' ) );
update_option( 'active_plugins', array() );
$data = $response->get_data();
$plugins = $data['active_plugins'];
$this->assertEquals( 1, count( $plugins ) );
$this->assertEquals( 'Hello Dolly', $plugins[0]['name'] );
}
/**
* Test to make sure theme response is correct.
*
* @since 2.7.0
*/
public function test_get_system_status_info_theme() {
wp_set_current_user( $this->user );
$active_theme = wp_get_theme();
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/system_status' ) );
$data = $response->get_data();
$theme = $data['theme'];
$this->assertEquals( 9, count( $theme ) );
$this->assertEquals( $active_theme->Name, $theme['name'] );
}
/**
* Test to make sure settings response is correct.
*
* @since 2.7.0
*/
public function test_get_system_status_info_settings() {
wp_set_current_user( $this->user );
$term_response = array();
$terms = get_terms( 'product_type', array( 'hide_empty' => 0 ) );
foreach ( $terms as $term ) {
$term_response[ $term->slug ] = strtolower( $term->name );
}
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/system_status' ) );
$data = $response->get_data();
$settings = $data['settings'];
$this->assertEquals( 10, count( $settings ) );
$this->assertEquals( ( 'yes' === get_option( 'woocommerce_api_enabled' ) ), $settings['api_enabled'] );
$this->assertEquals( get_woocommerce_currency(), $settings['currency'] );
$this->assertEquals( $term_response, $settings['taxonomies'] );
}
/**
* Test to make sure pages response is correct.
*
* @since 2.7.0
*/
public function test_get_system_status_info_pages() {
wp_set_current_user( $this->user );
$response = $this->server->dispatch( new WP_REST_Request( 'GET', '/wc/v1/system_status' ) );
$data = $response->get_data();
$pages = $data['pages'];
$this->assertEquals( 4, count( $pages ) );
}
/**
* Test system status schema.
*
* @since 2.7.0
*/
public function test_system_status_schema() {
$request = new WP_REST_Request( 'OPTIONS', '/wc/v1/system_status' );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$properties = $data['schema']['properties'];
$this->assertEquals( 6, count( $properties ) );
$this->assertArrayHasKey( 'environment', $properties );
$this->assertArrayHasKey( 'database', $properties );
$this->assertArrayHasKey( 'active_plugins', $properties );
$this->assertArrayHasKey( 'theme', $properties );
$this->assertArrayHasKey( 'settings', $properties );
$this->assertArrayHasKey( 'pages', $properties );
}
}

7
vendor/autoload.php vendored Normal file
View File

@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInit0a41505776925130d875dad51bde4180::getLoader();

413
vendor/composer/ClassLoader.php vendored Normal file
View File

@ -0,0 +1,413 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
* @see http://www.php-fig.org/psr/psr-0/
* @see http://www.php-fig.org/psr/psr-4/
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
private $classMapAuthoritative = false;
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Turns off searching the prefix and fallback directories for classes
* that have not been registered with the class map.
*
* @param bool $classMapAuthoritative
*/
public function setClassMapAuthoritative($classMapAuthoritative)
{
$this->classMapAuthoritative = $classMapAuthoritative;
}
/**
* Should class lookup fail if not found in the current class map?
*
* @return bool
*/
public function isClassMapAuthoritative()
{
return $this->classMapAuthoritative;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
if ('\\' == $class[0]) {
$class = substr($class, 1);
}
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
if ($this->classMapAuthoritative) {
return false;
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if ($file === null && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if ($file === null) {
// Remember that this class does not exist.
return $this->classMap[$class] = false;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
if (0 === strpos($class, $prefix)) {
foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

21
vendor/composer/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
Copyright (c) 2015 Nils Adermann, Jordi Boggiano
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

9
vendor/composer/autoload_classmap.php vendored Normal file
View File

@ -0,0 +1,9 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View File

@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

9
vendor/composer/autoload_psr4.php vendored Normal file
View File

@ -0,0 +1,9 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

45
vendor/composer/autoload_real.php vendored Normal file
View File

@ -0,0 +1,45 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInit0a41505776925130d875dad51bde4180
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInit0a41505776925130d875dad51bde4180', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInit0a41505776925130d875dad51bde4180', 'loadClassLoader'));
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
$loader->register(true);
return $loader;
}
}