s_array($meta)) { $meta = array(); } if (!is_array($attributes)) { $attributes = array($attributes); } foreach ($meta as $pa_key => $item) { if (in_array($item['name'], $attributes)) { $meta[$pa_key]['is_visible'] = $visible; } } update_post_meta($product_id, '_product_attributes', $meta); } public function set_product_attributes($product_id, $field_key, $value, $mode = 'replace') { if (!is_array($value)) { $value = array(intval($value)); } else { foreach ($value as $k => $tid) { $value[$k] = intval($tid); } } //*** $product = $this->get_product($product_id); $attributes = array(); $product_attributes = $product->get_attributes(); //*** fix for empty value if (count($value) === 1) { if (intval($value[0]) === 0) { $value = array(); } } //*** if (!empty($product_attributes)) { //wp-content\plugins\woocommerce\includes\admin\meta-boxes\class-wc-meta-box-product-data.php //public static function prepare_attributes foreach ($product_attributes as $pa_key => $a) { if (is_object($a)) { $attribute = new WC_Product_Attribute(); $attribute->set_id($a->get_id()); $attribute->set_name($a->get_name()); if ($a->get_name() == $field_key) { //detach attributes if there is no selected terms!! if (empty($value)) { continue; } //*** switch ($mode) { case 'append': //using in bulk $attribute->set_options(array_unique(array_merge($a->get_options(), $value))); break; case 'replace': case 'new': //using in bulk AND in editor $attribute->set_options($value); break; case 'remove': //using in bulk $attribute->set_options(array_values(array_diff($a->get_options(), $value))); break; case 'visible': //using in bulk $a->set_visible($value); break; } } else { $attribute->set_options($a->get_options()); } $attribute->set_position($a->get_position()); $attribute->set_visible($a->get_visible()); $attribute->set_variation($a->get_variation()); $attributes[] = $attribute; } } } //*** //if such attribute not applied in the product if (!isset($product_attributes[$field_key]) AND!isset($product_attributes[strtolower(urlencode($field_key))])) { $attribute = new WC_Product_Attribute(); $attribute_taxonomies = wc_get_attribute_taxonomies(); foreach ($attribute_taxonomies as $a) { if ('pa_' . $a->attribute_name == $field_key) { if (!empty($value)) { $attribute->set_id($a->attribute_id); $attribute->set_name('pa_' . $a->attribute_name); $attribute->set_options($value); $attribute->set_position(count($attributes)); $attribute->set_visible(1); $attribute->set_variation(true); $attributes[] = $attribute; } break; } } } $product->set_attributes($attributes); $product->save(); } //for saving downloads private function prepare_downloads($file_names, $file_urls, $file_hashes) { $downloads = array(); if (!empty($file_urls)) { $file_url_size = sizeof($file_urls); for ($i = 0; $i < $file_url_size; $i++) { if (!empty($file_urls[$i])) { $downloads[] = array( 'name' => wc_clean($file_names[$i]), 'file' => wp_unslash(trim($file_urls[$i])), 'previous_hash' => wc_clean($file_hashes[$i]), ); } } } return $downloads; } //++++++++++++++++++++++++++++++++++++++++ public function get_post_field($product_id, $field_key, $post_parent = 0) { if (!$product_id) { return FALSE; } //*** $res = ''; $field_type = $this->settings->get_fields()[$field_key]['field_type']; //fix for description of one variation if ($field_key == 'post_content' AND $post_parent > 0) { $field_type = 'meta'; $field_key = '_variation_description'; } //*** switch ($field_type) { case 'meta': $res = get_post_meta($product_id, $field_key, true); break; case 'field': $res = get_post_field($field_key, $product_id); break; case 'prop': $product = $this->get_product($product_id); //$field_key - for example: catalog_visibility $func_name = 'get_' . $field_key; //for example get_product_url() and get_button_text() exists only for external products if (method_exists($product, $func_name)) { $res = $product->$func_name(); } break; case 'taxonomy': $res = wp_get_post_terms($product_id, $this->settings->get_fields()[$field_key]['taxonomy'], array( //'fields' => 'ids', 'hide_empty' => false, )); break; case 'attribute': $product = $this->get_product($product_id); $attributes = $product->get_attributes(); if (!empty($attributes)) { if (!$product->is_type('variation')) { $res = array(); foreach ($attributes as $a) { if (is_object($a)) { if ($a->get_name() == $field_key) { $res = $a->get_options(); break; } } } } else { //a variation has NOT attributes as it is an attribute self //echo get_class($product); foreach ($attributes as $a) { if (is_object($a) AND method_exists($a, 'get_name')) { if ($a->get_name() == $field_key) { $t = get_term_by('slug', $a, $field_key); if (!empty($t)) { $res = array($t->term_id); } break; } } } } } break; case 'attribute_visibile': $product = $this->get_product($product_id); $attributes = $product->get_attributes(); if (!empty($attributes)) { if (!$product->is_type('variation')) { $res = array(); foreach ($attributes as $a) { if (is_object($a)) { if ($a->get_visible()) { $res[] = $a->get_visible(); } } } } // else { // //a variation has NOT attributes as it is an attribute self // //echo get_class($product); // foreach ($attributes as $a) { // if (is_object($a) AND method_exists($a, 'get_name')) { // if ($a->get_name() == $field_key) { // $t = get_term_by('slug', $a, $field_key); // if (!empty($t)) { // $res = array($t->term_id); // } // break; // } // } // } // } } break; case 'gallery': $product = $this->get_product($product_id); try { $res = $product->get_gallery_image_ids(); } catch (Exception $e) { $res = array(); } break; case 'downloads': try { $product = $this->get_product($product_id); $res = $product->get_downloads('edit'); } catch (Exception $e) { $res = array(); } break; case 'upsells': try { $product = $this->get_product($product_id); $res = $product->get_upsell_ids(); } catch (Exception $e) { $res = array(); } break; case 'cross_sells': try { $product = $this->get_product($product_id); $res = $product->get_cross_sell_ids(); } catch (Exception $e) { $res = array(); } break; case 'grouped': try { $product = $this->get_product($product_id); $res = $product->get_children('edit'); } catch (Exception $e) { $res = array(); } break; } return $res; } public function get_product($product_id, $use_cache = true) { $product_id = intval($product_id); if ($use_cache) { if (!isset($this->cached_products[$product_id])) { $this->cached_products[$product_id] = wc_get_product($product_id); } return $this->cached_products[$product_id]; } else { return wc_get_product($product_id); } /* $product_type = WC_Product_Factory::get_product_type($product_id); $classname = WC_Product_Factory::get_product_classname($product_id, $product_type); return new $classname($product_id); * */ } public function normalize_calendar_date($value, $field_key) { if ($field_key == 'post_date') { $date = new DateTime(); $date->setTimestamp(strtotime($value)); $value = $date->format('Y-m-d H:i:s'); return $value; } if ($value != 0) {//if not clearing // $value = explode('-', $value); if (isset($this->settings->active_fields[$field_key]['set_day_end']) AND $this->settings->active_fields[$field_key]['set_day_end']) { //$value = mktime(23, 59, 59, intval($value['1']), intval($value['2']), intval($value['0'])); $value = date('Y-m-d 23:59:59', (string) strtotime($value)); } else { //$value = mktime(0, 0, 0, intval($value['1']), intval($value['2']), intval($value['0'])); $value = date('Y-m-d 00:00:00', (string) strtotime($value)); } $value = (string) strtotime($value) - intval(get_option('gmt_offset')) * 3600; //*** //$gmt_offset = intval(get_option('gmt_offset')) * 3600; //$value += $gmt_offset; //*** if ($this->settings->active_fields[$field_key]['type'] === 'timestamp' AND $this->settings->active_fields[$field_key]['field_type'] === 'field') { $date = new DateTime(); $date->setTimestamp($value); /* if ($this->settings->active_fields[$field_key]['set_day_end']) { $value = $date->format('Y-m-d 23:59:59'); } else { $value = $date->format('Y-m-d 00:00:00'); } * */ $value = $date->format('Y-m-d H:i:s'); } } return $value; } public function get_attributes($product_id, $type = "all") { $product = $this->get_product($product_id); $attributes = $product->get_attributes(); $res = array(); if (!empty($attributes)) { if ($type == "visible") { $res = array(); foreach ($attributes as $a) { if (is_object($a)) { if ($a->get_visible()) { $res[] = $a; } } } } else { $res = $attributes; } } return $res; } //service public function string_replacer($val, $product_id) { if (is_string($val)) { if (stripos($val, '{TITLE}') !== false) { $val = str_ireplace('{TITLE}', $this->get_post_field($product_id, 'post_title'), $val); } if (stripos($val, '{ID}') !== false) { $val = str_ireplace('{ID}', $product_id, $val); } if (stripos($val, '{SKU}') !== false) { $val = str_ireplace('{SKU}', $this->get_post_field($product_id, 'sku'), $val); } //*** if (stripos($val, '{PARENT_TITLE}') !== false) { $p = $this->get_product($product_id); if ($p->is_type('variation')) { $val = str_ireplace('{PARENT_TITLE}', $this->get_post_field($p->get_parent_id(), 'post_title'), $val); } else { $val = str_ireplace('{PARENT_TITLE}', $this->get_post_field($product_id, 'post_title'), $val); } } if (stripos($val, '{PARENT_SKU}') !== false) { $p = $this->get_product($product_id); if ($p->is_type('variation')) { $val = str_ireplace('{PARENT_SKU}', $this->get_post_field($p->get_parent_id(), 'sku'), $val); } else { $val = str_ireplace('{PARENT_SKU}', $this->get_post_field($product_id, 'sku'), $val); } } if (stripos($val, '{PARENT_ID}') !== false) { $p = $this->get_product($product_id); if ($p->is_type('variation')) { $val = str_ireplace('{PARENT_ID}', $p->get_parent_id(), $val); } else { $val = str_ireplace('{PARENT_ID}', $product_id, $val); } } if (stripos($val, '{MENU_ORDER}') !== false) { $val = str_ireplace('{MENU_ORDER}', $this->get_post_field($product_id, 'menu_order'), $val); } if (stripos($val, '{REGULAR_PRICE}') !== false) { $val = str_ireplace('{REGULAR_PRICE}', $this->get_post_field($product_id, 'regular_price'), $val); } if (stripos($val, '{SALE_PRICE}') !== false) { $val = str_ireplace('{SALE_PRICE}', $this->get_post_field($product_id, 'sale_price'), $val); } //*** if (stripos($val, '{meta:') !== false) { //{meta:_woocs_regular_price_USD} - lets take data from metafield $val = explode(':', $val); $val = $this->get_post_field($product_id, trim($val[1], ' }')); } if (stripos($val, '{attribute:') !== false) { //{attribute:pa_size} $matches = array(); preg_match("/(?<={attribute:)(.*)(?=})/", $val, $matches); if (isset($matches[1])) { $prod = $this->get_product($product_id); $attr = $prod->get_attribute(trim($matches[1])); if (!empty($attr)) { $val = str_ireplace('{attribute:' . $matches[1] . "}", $attr, $val); } else { $val = str_ireplace('{attribute:' . $matches[1] . "}", "", $val); } } } } return apply_filters('woobe_apply_string_replacer', $val); } /** * Generates a title with attribute information for a variation. * Products will get a title of the form "Name - Value, Value" or just "Name". * * @since 3.0.0 * @param WC_Product * @return string */ public function generate_product_title($product) { $attributes = (array) $product->get_attributes(); // Do not include attributes if the product has 10+ attributes. $should_include_attributes = count($attributes) < 10; // Do not include attributes if an attribute name has 2+ words and the // product has multiple attributes. if ($should_include_attributes && 1 < count($attributes)) { foreach ($attributes as $name => $value) { if (false !== strpos($name, '-')) { $should_include_attributes = false; break; } } } $should_include_attributes = apply_filters('woocommerce_product_variation_title_include_attributes', $should_include_attributes, $product); $separator = apply_filters('woocommerce_product_variation_title_attributes_separator', ' - ', $product); //$parent_product = $this->get_product($product->get_parent_id()); $title_base = get_post_field('post_title', $product->get_parent_id()); if ($should_include_attributes) { $title_suffix = wc_get_formatted_variation($product, true, false); if (!empty($attributes)) { $title_suffix .= ' ['; $title_suffix .= implode(', ', array_map( function($str) { return str_replace('pa_', '', $str); }, array_map('urldecode', array_keys($attributes)) )); $title_suffix .= ']'; } } else { $title_suffix = ''; } //$title_suffix = $should_include_attributes ? wc_get_formatted_variation($product, true, false) : ''; return apply_filters('woocommerce_product_variation_title', $title_suffix ? $title_base . $separator . $title_suffix : $title_base, $product, $title_base, $title_suffix); } public function is_current_user_can_edit_field($field_key) { if ($this->settings->current_user_role != 'administrator') { $shop_manager_visibility = $this->settings->get_shop_manager_visibility(); $user_can = apply_filters('woobe_user_can_edit', $shop_manager_visibility[$field_key], $field_key, $shop_manager_visibility); if (!intval($user_can)) { return FALSE; } } return TRUE; } //service function to process serialized meta data public function process_jsoned_meta_data($raw_data) { $result = array(); //*** //for js arrays if (isset($raw_data['keys']) AND!empty($raw_data['keys'])) { $tmp = array(); foreach ($raw_data['keys'] as $kk => $kv) { if (!is_null($kv)) { if (!is_array($kv) AND isset($raw_data['keys'][$kv]) AND is_array($raw_data['keys'][$kv])) { if (!empty($raw_data['keys'][$kv])) { $tmp[WOOBE_HELPER::prepare_meta_keys($kv)] = array(); foreach ($raw_data['keys'][$kv] as $kkk => $vvv) { if (isset($raw_data['values'][$kv][$kkk])) { $tmp[WOOBE_HELPER::prepare_meta_keys($kv)][WOOBE_HELPER::prepare_meta_keys($vvv)] = $raw_data['values'][$kv][$kkk]; } } } } else { if (!is_array($kv)) { if (isset($raw_data['values'][WOOBE_HELPER::prepare_meta_keys($kk)])) { $tmp[WOOBE_HELPER::prepare_meta_keys($kv)] = $raw_data['values'][WOOBE_HELPER::prepare_meta_keys($kk)]; } } } } } $result = $tmp; } //*** //for js objects if (isset($raw_data['keys2']) AND!empty($raw_data['keys2'])) { $tmp = array(); foreach ($raw_data['keys2'] as $k => $keys) { if (!empty($keys)) { $o = array(); foreach ($keys as $kk => $key) { if ($this->is_json($raw_data['values2'][$k][$kk])) { $o[$key] = json_decode($raw_data['values2'][$k][$kk], ARRAY_A); } else { $o[$key] = $raw_data['values2'][$k][$kk]; } } $tmp[$k] = $o; } } $result = array_merge($result, $tmp); } //*** //if meta value is just string or number if (empty($result)) { $result = $raw_data; } return $result; } protected function clear_caches( &$product ) { wc_delete_product_transients( $product->get_id() ); if ( $product->get_parent_id( 'edit' ) ) { wc_delete_product_transients( $product->get_parent_id( 'edit' ) ); WC_Cache_Helper::invalidate_cache_group( 'product_' . $product->get_parent_id( 'edit' ) ); } WC_Cache_Helper::invalidate_attribute_count( array_keys( $product->get_attributes() ) ); WC_Cache_Helper::invalidate_cache_group( 'product_' . $product->get_id() ); } function is_json($string) { json_decode($string); return (json_last_error() == JSON_ERROR_NONE); } } ger/issues/208 * @since 6.0.0 Initial implementation of the method * * @access public * @version 6.8.3 */ public function getFromServer($param, $filter = FILTER_DEFAULT, $options = 0) { $var = filter_input(INPUT_SERVER, $param, $filter, $options); // Cover the unexpected server issues (e.g. FastCGI may cause unexpected null) if (empty($var)) { $var = filter_var( $this->readFromArray($_SERVER, $param), $filter, $options ); } return $var; } /** * Check array for specified parameter and return the it's value or * default one * * @param array $array Global array _GET, _POST etc * @param string $param Array Parameter * @param mixed $default Default value * * @return mixed * * @access protected * @version 6.0.0 */ protected function readFromArray($array, $param, $default = null) { $value = $default; if (is_null($param)) { $value = $array; } else { $chunks = explode('.', $param); $value = $array; foreach ($chunks as $chunk) { if (isset($value[$chunk])) { $value = $value[$chunk]; } else { $value = $default; break; } } } return $value; } }