stb0

class-wc-name-your-price-helpers.php

Sep 10th, 2020
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 35.85 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Static helper functions for interacting with products
  4.  *
  5.  * @class   WC_Name_Your_Price_Helpers
  6.  * @package WooCommerce Name Your Price/Classes
  7.  * @since   1.0.0
  8.  */
  9.  
  10. if ( ! defined( 'ABSPATH' ) ) {
  11.     exit;
  12. }
  13.  
  14. /**
  15.  * WC_Name_Your_Price_Helpers class.
  16.  */
  17. class WC_Name_Your_Price_Helpers {
  18.  
  19.     /**
  20.      * Supported product types.
  21.      * The nyp product type is how the ajax add to cart functionality is disabled in old version of WC.
  22.      *
  23.      * @var array
  24.      */
  25.     private static $simple_supported_types = array( 'simple', 'subscription', 'bundle', 'composite', 'variation', 'subscription_variation', 'deposit', 'mix-and-match' );
  26.  
  27.     /**
  28.      * Count the number of instance of an NYP input on a given page.
  29.      *
  30.      * @var int
  31.      */
  32.     private static $counter = 1;
  33.  
  34.     /**
  35.      * Supported variable product types.
  36.      *
  37.      * @var array
  38.      */
  39.     private static $variable_supported_types = array( 'variable', 'variable-subscription' );
  40.  
  41.     /**
  42.      * Get supported "simple" types.
  43.      *
  44.      * @return  array
  45.      * @since   2.7.0
  46.      */
  47.     public static function get_simple_supported_types() {
  48.         return apply_filters( 'wc_nyp_simple_supported_types', self::$simple_supported_types );
  49.     }
  50.  
  51.     /**
  52.      * Get supported "variable" types.
  53.      *
  54.      * @return  array
  55.      * @since   2.7.0
  56.      */
  57.     public static function get_variable_supported_types() {
  58.         return apply_filters( 'wc_nyp_variable_supported_types', self::$variable_supported_types );
  59.     }
  60.  
  61.     /**
  62.      * Verify this is a Name Your Price product.
  63.      *
  64.      * @param   mixed int|obj $product
  65.      * @return  return boolean
  66.      * @since   1.0
  67.      */
  68.     public static function is_nyp( $product ) {
  69.  
  70.         $product = self::maybe_get_product_instance( $product );
  71.  
  72.         if ( ! $product ) {
  73.             return false;
  74.         }
  75.  
  76.         $is_nyp = $product->is_type( self::get_simple_supported_types() ) && wc_string_to_bool( $product->get_meta( '_nyp' ) ) ? true : false;
  77.  
  78.         return apply_filters( 'wc_nyp_is_nyp', $is_nyp, $product->get_id(), $product );
  79.  
  80.     }
  81.  
  82.  
  83.     /**
  84.      * Get the suggested price.
  85.      *
  86.      * @param   mixed obj|int $product
  87.      * @return  mixed number|FALSE
  88.      * @since 2.0
  89.      */
  90.     public static function get_suggested_price( $product ) {
  91.  
  92.         $product = self::maybe_get_product_instance( $product );
  93.  
  94.         if ( ! $product ) {
  95.             return false;
  96.         }
  97.  
  98.         $suggested = $product->get_meta( '_suggested_price', true, 'edit' );
  99.  
  100.         if ( ! is_numeric( $suggested ) ) {
  101.             $suggested = false;
  102.         }
  103.  
  104.         // Filter the raw suggested price @since 1.2.
  105.         return apply_filters( 'wc_nyp_raw_suggested_price', $suggested, $product->get_id(), $product );
  106.  
  107.     }
  108.  
  109.     /**
  110.      * Get the minimum price.
  111.      *
  112.      * @param   mixed obj|int $product
  113.      * @return  mixed string|bool
  114.      * @since   2.0
  115.      */
  116.     public static function get_minimum_price( $product ) {
  117.  
  118.         $product = self::maybe_get_product_instance( $product );
  119.  
  120.         if ( ! $product ) {
  121.             return false;
  122.         }
  123.  
  124.         $minimum = $product->get_meta( '_min_price', true, 'edit' );
  125.  
  126.         if ( ! is_numeric( $minimum ) ) {
  127.             $minimum = false;
  128.         }
  129.  
  130.         // Filter the raw minimum price @since 1.2.
  131.         return apply_filters( 'wc_nyp_raw_minimum_price', $minimum, $product->get_id(), $product );
  132.  
  133.     }
  134.  
  135.     /**
  136.      * Get the maximum price.
  137.      *
  138.      * @param   mixed obj|int $product
  139.      * @return  return string
  140.      * @since   2.8.0
  141.      */
  142.     public static function get_maximum_price( $product ) {
  143.  
  144.         $product = self::maybe_get_product_instance( $product );
  145.  
  146.         if ( ! $product ) {
  147.             return false;
  148.         }
  149.  
  150.         $maximum = $product->get_meta( '_maximum_price', true, 'edit' );
  151.  
  152.         if ( ! is_numeric( $maximum ) ) {
  153.             $maximum = false;
  154.         }
  155.  
  156.         // Filter the raw maximum price @since 2.8.0.
  157.         return apply_filters( 'wc_nyp_raw_maximum_price', $maximum, $product->get_id(), $product );
  158.  
  159.     }
  160.  
  161.     /**
  162.      * Get the minimum price for a variable product.
  163.      *
  164.      * @param   mixed obj|int $product
  165.      * @return  return string
  166.      * @since   2.3
  167.      */
  168.     public static function get_minimum_variation_price( $product ) {
  169.  
  170.         $product = self::maybe_get_product_instance( $product );
  171.  
  172.         if ( ! $product ) {
  173.             return false;
  174.         }
  175.  
  176.         $minimum = $product->get_variation_price( 'min' );
  177.  
  178.         // Filter the raw minimum price @since 1.2.
  179.         return apply_filters( 'wc_nyp_raw_minimum_variation_price', $minimum, $product->get_id(), $product );
  180.  
  181.     }
  182.  
  183.     /**
  184.      * Check if Subscriptions plugin is installed and this is a subscription product.
  185.      *
  186.      * @param   mixed obj|int $product
  187.      * @return  return boolean returns true for subscription, variable-subscription and subscription_variation
  188.      * @since   2.0
  189.      */
  190.     public static function is_subscription( $product ) {
  191.  
  192.         return class_exists( 'WC_Subscriptions_Product' ) && WC_Subscriptions_Product::is_subscription( $product );
  193.  
  194.     }
  195.  
  196.  
  197.     /**
  198.      * Is the billing period variable.
  199.      *
  200.      * @param   mixed obj|int $product
  201.      * @return  return string
  202.      * @since   2.0
  203.      */
  204.     public static function is_billing_period_variable( $product ) {
  205.  
  206.         $product = self::maybe_get_product_instance( $product );
  207.  
  208.         if ( ! $product ) {
  209.             return false;
  210.         }
  211.  
  212.         $variable = $product->is_type( 'subscription' ) && wc_string_to_bool( $product->get_meta( '_variable_billing' ) ) ? true : false;
  213.  
  214.         return apply_filters( 'wc_nyp_is_billing_period_variable', $variable, $product->get_id() );
  215.     }
  216.  
  217.  
  218.     /**
  219.      * Get the Suggested Billing Period for subscription.
  220.      *
  221.      * @param   mixed obj|int $product.
  222.      * @return  return string
  223.      * @since   2.0
  224.      */
  225.     public static function get_suggested_billing_period( $product ) {
  226.  
  227.         $product = self::maybe_get_product_instance( $product );
  228.  
  229.         $period = $product->get_meta( '_suggested_billing_period' );
  230.  
  231.         // Set month as the default billing period.
  232.         if ( ! $period ) {
  233.             $period = 'month';
  234.         }
  235.  
  236.         // Filter the raw minimum price @since 1.2.
  237.         return apply_filters( 'wc_nyp_suggested_billing_period', $period, $product->get_id() );
  238.  
  239.     }
  240.  
  241.  
  242.     /**
  243.      * Get the Minimum Billing Period for subscriptsion
  244.      *
  245.      * @param   mixed obj|int $product
  246.      * @return  return string
  247.      * @since   2.0
  248.      */
  249.     public static function get_minimum_billing_period( $product ) {
  250.  
  251.         $product = self::maybe_get_product_instance( $product );
  252.  
  253.         $period = $product->get_meta( '_minimum_billing_period' );
  254.  
  255.         // Set month as the default billing period.
  256.         if ( ! $period ) {
  257.             $period = 'month';
  258.         }
  259.  
  260.         // Filter the raw minimum price @since 1.2.
  261.         return apply_filters( 'wc_nyp_minimum_billing_period', $period, $product->get_id() );
  262.  
  263.     }
  264.  
  265.  
  266.     /**
  267.      * Determine if variable has NYP variations.
  268.      *
  269.      * @param   mixed obj|int $product
  270.      * @return  return string
  271.      * @since   2.0
  272.      */
  273.     public static function has_nyp( $product ) {
  274.  
  275.         $product = self::maybe_get_product_instance( $product );
  276.  
  277.         if ( ! $product ) {
  278.             return false;
  279.         }
  280.  
  281.         $has_nyp = $product->is_type( self::get_variable_supported_types() ) && wc_string_to_bool( $product->get_meta( '_has_nyp', true, 'edit' ) ) ? true : false;
  282.  
  283.         return apply_filters( 'wc_nyp_has_nyp_variations', $has_nyp, $product );
  284.  
  285.     }
  286.  
  287.     /**
  288.      * Are we obscuring/hiding the minimum price.
  289.      *
  290.      * @param   mixed int|obj $product
  291.      * @return  return boolean
  292.      * @since   2.8.0
  293.      */
  294.     public static function is_minimum_hidden( $product ) {
  295.  
  296.         $product = self::maybe_get_product_instance( $product );
  297.  
  298.         if ( ! $product ) {
  299.             return false;
  300.         }
  301.  
  302.         $is_hidden = $product && wc_string_to_bool( $product->get_meta( '_hide_nyp_minimum' ) ) ? true : false;
  303.  
  304.         return apply_filters( 'wc_nyp_is_minimum_hidden', $is_hidden, $product->get_id(), $product );
  305.  
  306.     }
  307.  
  308.  
  309.     /**
  310.      * Are we hiding the From price for variable products.
  311.      *
  312.      * @param   mixed int|obj $product
  313.      * @return  return boolean
  314.      * @since   3.0.0
  315.      */
  316.     public static function is_variable_price_hidden( $product ) {
  317.  
  318.         $product = self::maybe_get_product_instance( $product );
  319.  
  320.         if ( ! $product ) {
  321.             return false;
  322.         }
  323.  
  324.         $is_hidden = $product && $product->get_meta( '_nyp_hide_variable_price' ) === 'yes' ? true : false;
  325.  
  326.         return apply_filters( 'wc_nyp_is_variable_price_hidden', $is_hidden, $product->get_id(), $product );
  327.  
  328.     }
  329.  
  330.     /**
  331.      *
  332.      * Standardize number to DB-friendly version
  333.      *
  334.      * Remove thousands separators, but cannot be run twice or currencies with . for thousands go from 100.00 to 10000!
  335.      *
  336.      * @return  return string
  337.      * @since   1.2.2
  338.      */
  339.     public static function standardize_number( $value ) {
  340.  
  341.         $value = trim( str_replace( wc_get_price_thousand_separator(), '', stripslashes( $value ) ) );
  342.  
  343.         return wc_format_decimal( $value );
  344.  
  345.     }
  346.  
  347.  
  348.     /**
  349.      * Annualize Subscription Price.
  350.      * convert price to "per year" so that prices with different billing periods can be compared
  351.      *
  352.      * @return  string
  353.      * @since   2.0
  354.      */
  355.     public static function annualize_price( $price = false, $period = null ) {
  356.  
  357.         $factors = self::annual_price_factors();
  358.  
  359.         if ( isset( $factors[ $period ] ) && $price ) {
  360.             $price = $factors[ $period ] * self::standardize_number( $price );
  361.         }
  362.  
  363.         return wc_format_decimal( $price );
  364.  
  365.     }
  366.  
  367.  
  368.     /**
  369.      * Annualize Subscription Price.
  370.      * convert price to "per year" so that prices with different billing periods can be compared
  371.      *
  372.      * @return  array
  373.      * @since   2.0
  374.      */
  375.     public static function annual_price_factors() {
  376.  
  377.         return array_map(
  378.             'esc_attr',
  379.             apply_filters(
  380.                 'wc_nyp_annual_factors',
  381.                 array(
  382.                     'day'   => 365,
  383.                     'week'  => 52,
  384.                     'month' => 12,
  385.                     'year'  => 1,
  386.                 )
  387.             )
  388.         );
  389.  
  390.     }
  391.  
  392.  
  393.     /**
  394.      * Get the "Minimum Price: $10" minimum string.
  395.      *
  396.      * @param   mixed obj|int $product
  397.      * @return  $price string
  398.      * @since   2.0
  399.      */
  400.     public static function get_minimum_price_html( $product ) {
  401.  
  402.         $product = self::maybe_get_product_instance( $product );
  403.  
  404.         // Start the price string.
  405.         $html = '';
  406.  
  407.         // If not nyp quit early.
  408.         if ( ! self::is_nyp( $product ) ) {
  409.             return $html;
  410.         }
  411.  
  412.         // Get the minimum price.
  413.         $minimum = self::get_minimum_price( $product );
  414.  
  415.         if ( false !== $minimum && ! self::is_minimum_hidden( $product ) ) {
  416.  
  417.             // Default minimum text.
  418.             $default_text = _x( 'Minimum price: %PRICE%', 'Name your price default minimum text', 'wc_name_your_price' );
  419.  
  420.             // Get the minimum text option.
  421.             $minimum_text = stripslashes( get_option( 'woocommerce_nyp_minimum_text', $default_text ) );
  422.  
  423.             // Replace placeholders.
  424.             $html = str_replace( '%PRICE%', wc_price( $minimum ), $minimum_text );
  425.  
  426.         }
  427.  
  428.         return apply_filters( 'wc_nyp_minimum_price_html', $html, $product );
  429.  
  430.     }
  431.  
  432.  
  433.     /**
  434.      * Get the "Suggested Price: $10" price string.
  435.      *
  436.      * @param   mixed obj|int $product
  437.      * @return  string
  438.      * @since   2.0
  439.      */
  440.     public static function get_suggested_price_html( $product ) {
  441.  
  442.         $product = self::maybe_get_product_instance( $product );
  443.  
  444.         // Start the price string.
  445.         $html = '';
  446.  
  447.         // If not nyp quit early.
  448.         if ( ! self::is_nyp( $product ) ) {
  449.             return $html;
  450.         }
  451.  
  452.         // Get suggested price.
  453.         $suggested = self::get_suggested_price( $product );
  454.  
  455.         if ( false !== $suggested ) {
  456.  
  457.             // Default suggested text.
  458.             $default_text = _x( 'Suggested price: %PRICE%', 'Name your price default suggested text', 'wc_name_your_price' );
  459.  
  460.             // Get the suggested text option.
  461.             $suggested_text = stripslashes( get_option( 'woocommerce_nyp_suggested_text', $default_text ) );
  462.  
  463.             // Replace placeholders.
  464.             $formatted_text = str_replace( '%PRICE%', wc_price( $suggested ), $suggested_text );
  465.  
  466.             // Put it all together.
  467.             $html .= sprintf( '<span class="suggested-text">%s</span>', $formatted_text );
  468.  
  469.         }
  470.  
  471.         return apply_filters( 'wc_nyp_suggested_price_html', $html, $product );
  472.  
  473.     }
  474.  
  475.     /**
  476.      * Get the "Name your price" label string.
  477.      *
  478.      * @param   mixed obj|int $product
  479.      * @return  string
  480.      * @since   2.11.0
  481.      */
  482.     public static function get_price_input_label_text( $product ) {
  483.  
  484.         $product = self::maybe_get_product_instance( $product );
  485.  
  486.         // Start the string.
  487.         $text = '';
  488.  
  489.         // If not nyp quit early.
  490.         if ( ! self::is_nyp( $product ) ) {
  491.             return $text;
  492.         }
  493.  
  494.         $currency_symbol = get_woocommerce_currency_symbol();
  495.  
  496.         // For subscriptions add the billing period.
  497.         if ( self::is_subscription( $product ) && ! self::is_billing_period_variable( $product ) ) {
  498.  
  499.             $include = array(
  500.                 'price'               => get_woocommerce_currency_symbol(),
  501.                 'tax_calculation'     => false,
  502.                 'subscription_price'  => true,
  503.                 'subscription_period' => true,
  504.                 'subscription_length' => false,
  505.                 'sign_up_fee'         => false,
  506.                 'trial_length'        => false,
  507.             );
  508.  
  509.             $currency_symbol = WC_Subscriptions_Product::get_price_string( $product, $include );
  510.  
  511.         }
  512.  
  513.         // Translators: %1$s is the currency symbol and %2$s is the currency symbol.
  514.         $text = sprintf(
  515.             // Translators: %1$s is the label text and %2$s is the currency symbol.
  516.             _x( '%1$s ( %2$s )', 'Name your price input label', 'wc_name_your_price' ),
  517.             esc_html( get_option( 'woocommerce_nyp_label_text', __( 'Name your price', 'wc_name_your_price' ) ) ),
  518.             $currency_symbol
  519.         );
  520.  
  521.         return apply_filters( 'wc_nyp_price_input_label_text', $text, $product );
  522.  
  523.     }
  524.  
  525.  
  526.     /**
  527.      * Format a price string.
  528.      *
  529.      * @param   mixed obj|int $product
  530.      * @param   string        $type ( minimum or suggested )
  531.      * @param   bool          $show_null_as_zero in the admin you may wish to have a null string display as $0.00
  532.      * @param   bool          $show_raw_price (optional) uses the wc_price() if set to false
  533.      * @return  string
  534.      * @since   2.0
  535.      */
  536.     public static function get_price_string( $product, $type = 'suggested', $show_null_as_zero = false, $show_raw_price = false ) {
  537.  
  538.         // Start the price string.
  539.         $html = '';
  540.  
  541.         $product = self::maybe_get_product_instance( $product );
  542.  
  543.         // Minimum or suggested price.
  544.         switch ( $type ) {
  545.             case 'minimum-variation':
  546.                 $price = self::get_minimum_variation_price( $product );
  547.                 break;
  548.             case 'minimum':
  549.                 $price = self::get_minimum_price( $product );
  550.                 break;
  551.             default:
  552.                 $price = self::get_suggested_price( $product );
  553.                 break;
  554.         }
  555.  
  556.         if ( $show_null_as_zero || '' !== $price ) {
  557.             $price = $show_raw_price ? $price : wc_price( $price );
  558.             // Set the billing period to either suggested or minimum.
  559.             if ( self::is_subscription( $product ) && self::is_billing_period_variable( $product ) ) {
  560.                 // Minimum or suggested period.
  561.                 $period = 'minimum' === $type ? self::get_minimum_billing_period( $product ) : self::get_suggested_billing_period( $product );
  562.  
  563.                 $product->update_meta_data( '_subscription_period', $period );
  564.             }
  565.  
  566.             // Get subscription price string.
  567.             // If you filter woocommerce_get_price_html you end up doubling the period $99 / month / week.
  568.             // As Subs add the string after the woocommerce_get_price_html filter has run.
  569.             if ( self::is_subscription( $product ) && 'woocommerce_get_price_html' !== current_filter() ) {
  570.  
  571.                 $include = array(
  572.                     'price'               => $price,
  573.                     'subscription_length' => false,
  574.                     'sign_up_fee'         => false,
  575.                     'trial_length'        => false,
  576.                 );
  577.  
  578.                 $html = WC_Subscriptions_Product::get_price_string( $product, $include );
  579.  
  580.                 // Non-subscription products.
  581.             } else {
  582.                 $html = $price;
  583.             }
  584.         }
  585.  
  586.         return apply_filters( 'wc_nyp_price_string', $html, $product, $price );
  587.  
  588.     }
  589.  
  590.  
  591.     /**
  592.      * Get Price Value Attribute.
  593.      *
  594.      * @param   mixed obj|int $product
  595.      * @return  string
  596.      * @since   2.1
  597.      */
  598.     public static function get_price_value_attr( $product, $suffix = false ) {
  599.  
  600.         $product = self::maybe_get_product_instance( $product );
  601.         $posted  = self::get_posted_price( $product, $suffix );
  602.  
  603.         if ( '' !== $posted ) {
  604.             $price = $posted;
  605.         } else {
  606.             $price = self::get_initial_price( $product );
  607.         }
  608.  
  609.         return $price;
  610.     }
  611.  
  612.  
  613.     /**
  614.      * Get Posted Price.
  615.      *
  616.      * @param   mixed obj|int $product
  617.      * @param   string        $suffix - needed for composites and bundles
  618.      * @return  string
  619.      * @since   2.0
  620.      */
  621.     public static function get_posted_price( $product = false, $suffix = false ) {
  622.         // phpcs:disable WordPress.Security.NonceVerification
  623.         $product = self::maybe_get_product_instance( $product );
  624.  
  625.         // The $product is now useless, so we can deprecate that in the future? // Leave in Filter.
  626.         $posted_price = isset( $_REQUEST[ 'nyp' . $suffix ] ) ? self::standardize_number( sanitize_text_field( wp_unslash( $_REQUEST[ 'nyp' . $suffix ] ) ) ) : '';
  627.  
  628.         return apply_filters( 'wc_nyp_get_posted_price', $posted_price, $product, $suffix );
  629.     }
  630.  
  631.  
  632.     /**
  633.      * Get Initial Price
  634.      *
  635.      * As of 3.0 this is now null by default for accessibility reasons.
  636.      *
  637.      * @param   mixed obj|int $product
  638.      * @return  string
  639.      * @since   2.1
  640.      */
  641.     public static function get_initial_price( $product ) {
  642.  
  643.         $product = self::maybe_get_product_instance( $product );
  644.  
  645.         return apply_filters( 'wc_nyp_get_initial_price', '', $product );
  646.     }
  647.  
  648.     /**
  649.      * Get Period Value Attribute.
  650.      *
  651.      * @param   mixed int|object $product
  652.      * @return  string
  653.      * @since   2.7.0
  654.      */
  655.     public static function get_period_value_attr( $product, $suffix = false ) {
  656.  
  657.         $product = self::maybe_get_product_instance( $product );
  658.         $posted  = self::get_posted_period( $product, $suffix );
  659.  
  660.         if ( '' !== $posted ) {
  661.             $price = $posted;
  662.         } else {
  663.             $price = self::get_initial_period( $product );
  664.         }
  665.  
  666.         return $price;
  667.     }
  668.  
  669.     /**
  670.      * Get Posted Billing Period.
  671.      *
  672.      * @param   string $product - not needed
  673.      * @param   string $suffix - needed for composites and bundles
  674.      * @return  string
  675.      * @since   2.0
  676.      */
  677.     public static function get_posted_period( $product = false, $suffix = false ) {
  678.         // phpcs:disable WordPress.Security.NonceVerification
  679.         $product = self::maybe_get_product_instance( $product );
  680.  
  681.         // The $product is now useless, so we can deprecate that in the future?
  682.         $posted_period = isset( $_REQUEST[ 'nyp-period' . $suffix ] ) && array_key_exists( sanitize_key( $_REQUEST[ 'nyp-period' . $suffix ] ), self::get_subscription_period_strings() ) ? sanitize_key( $_REQUEST[ 'nyp-period' . $suffix ] ) : '';
  683.         return apply_filters( 'wc_nyp_get_posted_period', $posted_period, $product, $suffix );
  684.     }
  685.  
  686.     /**
  687.      * Get Initial Billing Period.
  688.      *
  689.      * @param   mixed obj|int $product
  690.      * @param   string        $suffix - needed for composites and bundles
  691.      * @return  string
  692.      * @since   2.7.0
  693.      */
  694.     public static function get_initial_period( $product ) {
  695.  
  696.         $product = self::maybe_get_product_instance( $product );
  697.  
  698.         $suggested_period = self::get_suggested_billing_period( $product );
  699.         $minimum_period   = self::get_minimum_billing_period( $product );
  700.         // Go through a few options to find the $period we should display.
  701.         if ( $suggested_period ) {
  702.             $period = $suggested_period;
  703.         } elseif ( $minimum_period ) {
  704.             $period = $minimum_period;
  705.         } else {
  706.             $period = 'month';
  707.         }
  708.         return $period;
  709.     }
  710.  
  711.     /**
  712.      * Generate markup for NYP Price input.
  713.      * Returns a text input with formatted value.
  714.      *
  715.      * @param   mixed obj|int $product
  716.      * @param   string        $suffix - needed for composites and bundles
  717.      * @return  string
  718.      * @since   2.0
  719.      */
  720.     public static function get_price_input( $product, $suffix = false ) {
  721.  
  722.         wc_deprecated_function( 'WC_Name_Your_Price_Helpers::get_price_input()', '3.0.0', 'Input HTML is displayed directly in the price-input.php template where it can be safely escaped.' );
  723.  
  724.         $product = self::maybe_get_product_instance( $product );
  725.         $price   = self::get_price_value_attr( $product, $suffix );
  726.         $counter = self::get_counter();
  727.  
  728.         $attributes = array(
  729.             'id'               => 'nyp-' . $counter,
  730.             'name'             => 'nyp' . $suffix,
  731.             'type'             => 'text',
  732.             'value'            => self::format_price( $price ),
  733.             'title'            => self::get_price_input_label_text( $product ),
  734.             'class'            => array( 'input-text', 'amount', 'nyp-input', 'text' ),
  735.             'aria-describedby' => array( 'nyp-minimum-price-' . $counter, 'nyp-error-' . $counter ),
  736.         );
  737.  
  738.         /**
  739.          * Filter wc_nyp_price_input_attributes
  740.          *
  741.          * @param  array $attributes The array of attributes for the NYP div
  742.          * @param  obj $product WC_Product The product object
  743.          * @param  string $suffix - needed for grouped, composites, bundles, etc.
  744.          * @return string
  745.          * @since  2.11.0
  746.          */
  747.         $attributes = apply_filters( 'wc_nyp_price_input_attributes', $attributes, $product, $suffix );
  748.  
  749.         $input = '';
  750.  
  751.         // Build the input element.
  752.         foreach ( $attributes as $key => $attribute ) {
  753.             $attribute = is_array( $attribute ) ? implode( ' ', $attribute ) : $attribute;
  754.             $input    .= sprintf( '%s="%s" ', esc_attr( $key ), esc_attr( $attribute ) );
  755.         }
  756.  
  757.         $input = sprintf( '<input %s/>', $input );
  758.  
  759.         // Prepend label.
  760.         $label_text = self::get_price_input_label_text( $product );
  761.  
  762.         if ( $label_text || self::has_nyp( $product ) ) {
  763.             $label_html = '<label id="nyp-label-' . self::get_counter() . '" for="' . $attributes['id'] . '">' . $label_text . '</label>';
  764.             $input      = $label_html . $input;
  765.         }
  766.  
  767.         // Append hidden input for updating price.
  768.         if ( isset( $_GET['update-price'] ) ) {
  769.             $updating_cart_key = wc_clean( wp_unslash( $_GET['update-price'] ) );
  770.             if ( isset( WC()->cart->cart_contents[ $updating_cart_key ] ) ) {
  771.                 $input .= '<input type="hidden" name="update-price" value="' . $updating_cart_key . '" />';
  772.             }
  773.         }
  774.  
  775.         /**
  776.          * Filter woocommerce_get_price_input
  777.          *
  778.          * @param  string $html - the resulting input's html.
  779.          * @param  int    $product_id - the product id.
  780.          * @param  string $suffix - needed for grouped, composites, bundles, etc.
  781.          * @return string
  782.          * @deprecated 3.0.0
  783.          */
  784.         if ( has_filter( 'woocommerce_get_price_input' ) ) {
  785.             wc_doing_it_wrong( __FUNCTION__, 'woocommerce_get_price_input filter has been removed for security reasons! Please consider using the wc_nyp_price_input_attributes filter to modify attributes or overriding the price-input.php template.', '3.0' );
  786.         }
  787.  
  788.         return $input;
  789.  
  790.     }
  791.  
  792.     /**
  793.      * Generate Markup for Subscription Period Input.
  794.      *
  795.      * @param   string        $input
  796.      * @param   mixed obj|int $product
  797.      * @param   string        $suffix - needed for composites and bundles
  798.      * @return  string
  799.      * @since   2.0
  800.      */
  801.     public static function get_subscription_period_input( $input, $product, $suffix ) {
  802.  
  803.         // Get product object.
  804.         $product = self::maybe_get_product_instance( $product );
  805.  
  806.         // Create the dropdown select element.
  807.         $period = self::get_period_value_attr( $product, $suffix );
  808.  
  809.         // The pre-selected value.
  810.         $selected = $period ? $period : 'month';
  811.  
  812.         // Get list of available periods from Subscriptions plugin.
  813.         $periods = self::get_subscription_period_strings();
  814.  
  815.         if ( $periods ) :
  816.  
  817.             $period_input = sprintf( '<span class="per">/ </span><select id="nyp-period%s" name="nyp-period%s" class="nyp-period">', self::get_counter(), $suffix );
  818.  
  819.             foreach ( $periods as $i => $period ) :
  820.                 $period_input .= sprintf( '<option value="%s" %s>%s</option>', $i, selected( $i, $selected, false ), $period );
  821.             endforeach;
  822.  
  823.             $period_input .= '</select>';
  824.  
  825.             $period_input = '<span class="nyp-billing-period"> ' . $period_input . '</span>';
  826.  
  827.             /**
  828.              * Filter wc_nyp_subscription_period_input
  829.              *
  830.              * @param  string $period_input - the resulting input's html.
  831.              * @param  obj    $product - the product object.
  832.              * @param  string $suffix - needed for grouped, composites, bundles, etc.
  833.              * @return string
  834.              * @deprecated 3.0.0
  835.              */
  836.             if ( has_filter( 'wc_nyp_subscription_period_input' ) ) {
  837.                 wc_doing_it_wrong( __FUNCTION__, 'wc_nyp_subscription_period_input filter has been removed for security reasons!', '3.0' );
  838.             }
  839.             $input .= $period_input;
  840.  
  841.         endif;
  842.  
  843.         return $input;
  844.  
  845.     }
  846.  
  847.     /**
  848.      * Format price with local decimal point.
  849.      * Similar to wc_price().
  850.      *
  851.      * @param   string $price
  852.      * @return  string
  853.      * @since   2.1
  854.      */
  855.     public static function format_price( $price ) {
  856.  
  857.         $decimals           = wc_get_price_decimals();
  858.         $decimal_separator  = wc_get_price_decimal_separator();
  859.         $thousand_separator = wc_get_price_thousand_separator();
  860.  
  861.         if ( '' !== $price ) {
  862.  
  863.             $price = apply_filters( 'raw_woocommerce_price', floatval( $price ) );
  864.             $price = apply_filters( 'formatted_woocommerce_price', number_format( $price, $decimals, $decimal_separator, $thousand_separator ), $price, $decimals, $decimal_separator, $thousand_separator );
  865.  
  866.             if ( apply_filters( 'wc_nyp_price_trim_zeros', false ) && $decimals > 0 ) {
  867.                 $price = wc_trim_zeros( $price );
  868.             }
  869.         }
  870.  
  871.         return $price;
  872.     }
  873.  
  874.     /**
  875.      * Generate Markup for minimum price + subscription terms.
  876.      *
  877.      * @param   mixed obj|int $product
  878.      * @return  string
  879.      * @since   3.0
  880.      */
  881.     public static function get_price_terms_html( $product ) {
  882.  
  883.         // Get product object.
  884.         $product = self::maybe_get_product_instance( $product );
  885.  
  886.         $minimum_price_html = self::get_minimum_price_html( $product );
  887.         $subscription_terms = self::get_subscription_terms_html( $product );
  888.  
  889.         if ( $minimum_price_html && $subscription_terms ) {
  890.             // Translators: %1$s is minimum price html. %2$s subscription terms.
  891.             $terms = sprintf( __( '%1$s %2$s', 'wc_name_your_price' ), $minimum_price_html, $subscription_terms );
  892.         } elseif ( $minimum_price_html ) {
  893.             $terms = $minimum_price_html;
  894.         } else {
  895.             $terms = $subscription_terms;
  896.         }
  897.  
  898.         return $terms;
  899.  
  900.     }
  901.  
  902.     /**
  903.      * Generate Markup for subscription terms.
  904.      *
  905.      * @param   mixed obj|int $product
  906.      * @return  string
  907.      * @since   3.0
  908.      */
  909.     public static function get_subscription_terms_html( $product ) {
  910.  
  911.         // Get product object.
  912.         $product = self::maybe_get_product_instance( $product );
  913.  
  914.         $terms = '';
  915.  
  916.         // Parent variable subscriptions don't have a billing period, so we get a array to string notice. therefore only apply to simple subs and sub variations.
  917.         if ( $product->is_type( 'subscription' ) || $product->is_type( 'subscription_variation' ) ) {
  918.  
  919.             $minimum = self::get_minimum_price( $product );
  920.  
  921.             $includes = array();
  922.  
  923.             $billing_interval    = intval( WC_Subscriptions_Product::get_interval( $product ) );
  924.             $subscription_length = intval( WC_Subscriptions_Product::get_length( $product ) );
  925.  
  926.             if ( 1 === $billing_interval && $billing_interval !== $subscription_length ) {
  927.  
  928.                 if ( self::is_billing_period_variable( $product ) ) {
  929.                     $period = self::get_minimum_billing_period( $product );
  930.                 } else {
  931.                     $period = WC_Subscriptions_Product::get_period( $product );
  932.                 }
  933.  
  934.                 // Get translated period.
  935.                 $period = wcs_get_subscription_period_strings( $billing_interval, $period );
  936.  
  937.                 if ( $minimum && ! self::is_minimum_hidden( $product ) ) {
  938.                     // Translators: %1$s is null string because minimum price is displayed elsewhere. %2$s is minimum billing period.
  939.                     $price_string = sprintf( __( '%1$s every %2$s', 'wc_name_your_price' ), '', $period );
  940.                 } else {
  941.                     // Translators: %s is minimum billing period.
  942.                     $price_string = sprintf( __( 'Due every %s', 'wc_name_your_price' ), $period );
  943.                 }
  944.  
  945.                 $includes['subscription_period'] = false;
  946.  
  947.             } else {
  948.  
  949.                 if ( $minimum && ! self::is_minimum_hidden( $product ) ) {
  950.                     $price_string = '';
  951.                 } else {
  952.                     $price_string = __( 'Due', 'wc_name_your_price' );
  953.                 }
  954.             }
  955.  
  956.             $includes['price'] = $price_string;
  957.  
  958.             $terms = WC_Subscriptions_Product::get_price_string( $product, $includes );
  959.  
  960.         }
  961.  
  962.         return apply_filters( 'wc_nyp_subscriptions_terms_html', $terms, $product );
  963.  
  964.     }
  965.  
  966.     /**
  967.      * Generate Markup for Subscription Periods.
  968.      *
  969.      * @param   string        $input
  970.      * @param   mixed obj|int $product
  971.      * @return  string
  972.      * @since   2.0
  973.      */
  974.     public static function get_subscription_terms( $input = '', $product ) {
  975.  
  976.         $terms = '&nbsp;';
  977.  
  978.         // Get product object.
  979.         $product = self::maybe_get_product_instance( $product );
  980.  
  981.         // Parent variable subscriptions don't have a billing period, so we get a array to string notice. therefore only apply to simple subs and sub variations.
  982.         if ( $product->is_type( 'subscription' ) || $product->is_type( 'subscription_variation' ) ) {
  983.  
  984.             if ( self::is_billing_period_variable( $product ) ) {
  985.                 // Don't display the subscription price, period or length.
  986.                 $include = array(
  987.                     'price'               => '',
  988.                     'subscription_price'  => false,
  989.                     'subscription_period' => false,
  990.                 );
  991.  
  992.             } else {
  993.                 $include = array(
  994.                     'price'              => '',
  995.                     'subscription_price' => false,
  996.                 );
  997.                 // If we don't show the price we don't get the "per" backslash so add it back.
  998.                 if ( WC_Subscriptions_Product::get_interval( $product ) === 1 ) {
  999.                     $terms .= '<span class="per">/ </span>';
  1000.                 }
  1001.             }
  1002.  
  1003.             $terms .= WC_Subscriptions_Product::get_price_string( $product, $include );
  1004.  
  1005.         }
  1006.  
  1007.         // Piece it all together - JS needs a span with this class to change terms on variation found event.
  1008.         // Use details class to mimic Subscriptions plugin, leave terms class for backcompat.
  1009.         if ( 'wc_nyp_get_price_input' === current_filter() ) {
  1010.             $terms = '<span class="subscription-details subscription-terms">' . $terms . '</span>';
  1011.         }
  1012.  
  1013.         return $input . $terms;
  1014.  
  1015.     }
  1016.  
  1017.  
  1018.     /**
  1019.      * Get data attributes for use in name-your-price.js
  1020.      *
  1021.      * @param   mixed obj|int $product
  1022.      * @param   string        $suffix - needed for composites and bundles
  1023.      * @return  string
  1024.      * @since   2.0
  1025.      */
  1026.     public static function get_data_attributes( $product, $suffix = null ) {
  1027.  
  1028.         // Get product object.
  1029.         $product = self::maybe_get_product_instance( $product );
  1030.  
  1031.         $price   = (float) self::get_price_value_attr( $product, $suffix );
  1032.         $minimum = self::get_minimum_price( $product );
  1033.  
  1034.         $attributes = array(
  1035.             'minimum-error'      => self::error_message( 'minimum_js' ),
  1036.             'hide-minimum'       => self::is_minimum_hidden( $product ),
  1037.             'hide-minimum-error' => self::error_message( 'hide_minimum_js' ),
  1038.             'max-price'          => self::get_maximum_price( $product ),
  1039.             'maximum-error'      => self::error_message( 'maximum_js' ),
  1040.             'empty-error'        => self::error_message( 'empty' ),
  1041.             'initial-price'      => self::get_initial_price( $product ),
  1042.         );
  1043.  
  1044.         if ( self::is_subscription( $product ) && self::is_billing_period_variable( $product ) ) {
  1045.  
  1046.                 $period             = self::get_period_value_attr( $product, $suffix );
  1047.                 $minimum_period     = self::get_minimum_billing_period( $product );
  1048.                 $annualized_minimum = self::annualize_price( $minimum, $minimum_period );
  1049.  
  1050.                 $attributes['period']         = esc_attr( $period ) ? esc_attr( $period ) : 'month';
  1051.                 $attributes['annual-minimum'] = $annualized_minimum > 0 ? (float) $annualized_minimum : 0;
  1052.  
  1053.         } else {
  1054.  
  1055.             $attributes['min-price'] = $minimum && $minimum > 0 ? (float) $minimum : 0;
  1056.  
  1057.         }
  1058.  
  1059.         /**
  1060.          * Filter wc_nyp_data_attributes
  1061.          *
  1062.          * @param  array $attributes The array of attributes for the NYP div
  1063.          * @param  obj $product WC_Product The product object
  1064.          * @param  string $suffix - needed for grouped, composites, bundles, etc.
  1065.          * @return string
  1066.          * @since  2.11.0
  1067.          */
  1068.         $attributes = apply_filters( 'wc_nyp_data_attributes', $attributes, $product, $suffix );
  1069.  
  1070.         $data_string = '';
  1071.  
  1072.         foreach ( $attributes as $key => $attribute ) {
  1073.             $data_string .= sprintf( 'data-%s="%s" ', esc_attr( $key ), esc_attr( $attribute ) );
  1074.         }
  1075.  
  1076.         return $data_string;
  1077.  
  1078.     }
  1079.  
  1080.  
  1081.     /**
  1082.      * The error message template.
  1083.      *
  1084.      * @param   string $id - selects which message to use
  1085.      * @param   string $context - optionally varies the template $id by the validation context.
  1086.      * @return  return string
  1087.      * @since   2.1
  1088.      */
  1089.     public static function get_error_message_template( $id = null, $context = '' ) {
  1090.  
  1091.         $errors = apply_filters(
  1092.             'wc_nyp_error_message_templates',
  1093.             array(
  1094.                 'invalid-product' => __( 'This is not a valid product.', 'wc_name_your_price' ),
  1095.                 'invalid'         => __( '&quot;%%TITLE%%&quot; could not be added to the cart. Please enter a valid, positive number.', 'wc_name_your_price' ),
  1096.                 'minimum'         => __( '&quot;%%TITLE%%&quot; could not be added to the cart. Please enter at least %%MINIMUM%%.', 'wc_name_your_price' ),
  1097.                 'hide_minimum'    => __( '&quot;%%TITLE%%&quot; could not be added to the cart. Please enter a higher amount.', 'wc_name_your_price' ),
  1098.                 'minimum_js'      => __( 'Please enter at least %%MINIMUM%%.', 'wc_name_your_price' ),
  1099.                 'hide_minimum_js' => __( 'Please enter a higher amount.', 'wc_name_your_price' ),
  1100.                 'maximum'         => __( '&quot;%%TITLE%%&quot; could not be added to the cart. Please enter less than or equal to %%MAXIMUM%%.', 'wc_name_your_price' ),
  1101.                 'maximum_js'      => __( 'Please enter less than or equal to %%MAXIMUM%%.', 'wc_name_your_price' ),
  1102.                 'empty'           => __( 'Please enter an amount.', 'wc_name_your_price' ),
  1103.                 'minimum-cart'    => __( '&quot;%%TITLE%%&quot; cannot be purchased. Please enter at least %%MINIMUM%%.', 'wc_name_your_price' ),
  1104.                 'maximum-cart'    => __( '&quot;%%TITLE%%&quot; cannot be purchased. Please enter less than or equal to %%MAXIMUM%%.', 'wc_name_your_price' ),
  1105.             )
  1106.         );
  1107.  
  1108.         if ( isset( $errors[ $id . '-' . $context ] ) ) {
  1109.             $template = $errors[ $id . '-' . $context ];
  1110.         } elseif ( isset( $errors[ $id ] ) ) {
  1111.             $template = $errors[ $id ];
  1112.         } else {
  1113.             $template = '';
  1114.         }
  1115.  
  1116.         return $template;
  1117.  
  1118.     }
  1119.  
  1120.  
  1121.     /**
  1122.      * Get error message.
  1123.      *
  1124.      * @param   string $id - the error template to use
  1125.      * @param   array  $tags - array of tags and their respective replacement values
  1126.      * @param   obj    $product - the relevant product object
  1127.      * @param   string $context - the validation context
  1128.      * @return  return string
  1129.      * @since   2.1
  1130.      */
  1131.     public static function error_message( $id, $tags = array(), $product = null, $context = '' ) {
  1132.  
  1133.         $message = self::get_error_message_template( $id, $context );
  1134.  
  1135.         foreach ( $tags as $tag => $value ) {
  1136.             $message = str_replace( $tag, $value, $message );
  1137.         }
  1138.  
  1139.         return apply_filters( 'wc_nyp_error_message', $message, $id, $tags, $product );
  1140.  
  1141.     }
  1142.  
  1143.  
  1144.     /**
  1145.      * Return an i18n'ified associative array of all possible subscription periods.
  1146.      * Ready for Subs 2.0 but with backcompat.
  1147.      *
  1148.      * @since 2.2.8
  1149.      */
  1150.     public static function get_subscription_period_strings( $number = 1, $period = '' ) {
  1151.         if ( function_exists( 'wcs_get_subscription_period_strings' ) ) {
  1152.             $strings = wcs_get_subscription_period_strings( $number, $period );
  1153.         } else {
  1154.             $strings = WC_Subscriptions_Manager::get_subscription_period_strings( $number, $period );
  1155.         }
  1156.         return apply_filters( 'wc_nyp_subscription_strings', $strings, $number, $period );
  1157.     }
  1158.  
  1159.     /**
  1160.      * Wrapper to check whether we have a product ID or product and if we have the former, return the later.
  1161.      *
  1162.      * @props Prospress!
  1163.      *
  1164.      * @param int|WC_Product $product_id A WC_Product object or product ID
  1165.      * @return WC_Product
  1166.      * @since 2.2.0
  1167.      */
  1168.     public static function maybe_get_product_instance( $product ) {
  1169.  
  1170.         if ( ! is_object( $product ) || ! is_a( $product, 'WC_Product' ) ) {
  1171.             $product = wc_get_product( $product );
  1172.         }
  1173.  
  1174.         return $product;
  1175.     }
  1176.  
  1177.     /**
  1178.      * Get the current count
  1179.      *
  1180.      * @return int
  1181.      * @since 3.0.0
  1182.      */
  1183.     public static function get_counter() {
  1184.         return self::$counter;
  1185.     }
  1186.  
  1187.     /**
  1188.      * Increase the current count
  1189.      *
  1190.      * @return int
  1191.      * @since 3.0.0
  1192.      */
  1193.     public static function increase_counter() {
  1194.         self::$counter++;
  1195.     }
  1196.  
  1197.     /**
  1198.      * Get the Suffix
  1199.      *
  1200.      * @param int $nyp_id - A product|variation ID.
  1201.      * @return string
  1202.      * @since 3.0
  1203.      */
  1204.     public static function get_suffix( $nyp_id ) {
  1205.         return apply_filters( 'wc_nyp_field_suffix', '', $nyp_id );
  1206.     }
  1207.  
  1208.  
  1209.     /**
  1210.      * ---------------------------------------------------------------------------------
  1211.      * Deprecated Functions
  1212.      * ---------------------------------------------------------------------------------
  1213.      */
  1214.  
  1215.     /**
  1216.      * Get the prefix (Yes I'm aware I'm using it as a suffix... whoops)
  1217.      *
  1218.      * @param int $nyp_id - A product|variation ID.
  1219.      * @return string
  1220.      * @since 2.11.0
  1221.      * @deprecated 3.0
  1222.      */
  1223.     public static function get_prefix( $nyp_id ) {
  1224.         wc_deprecated_function( 'WC_Name_Your_Price_Helpers::get_prefix()', '3.0.0', 'Function replaced with WC_Name_Your_Price_Helpers::get_suffix()' );
  1225.         return self::get_suffix( $nyp_id );
  1226.     }
  1227.  
  1228. }//end class
  1229.  
Advertisement
Add Comment
Please, Sign In to add comment