/** * Decode property. * * @param string $key * @param string $value * * @return mixed */ protected function decode_property($key, $value) { if (papi_is_property_type_key($key) && is_string($value)) { $value = base64_decode($value); $value = papi_maybe_json_decode($value); } return $value; }
/** * Format the value of the property before it's returned * to WordPress admin or the site. * * @param mixed $value * @param string $slug * @param int $post_id * * @return array */ public function format_value($value, $slug, $post_id) { if (!$this->get_setting('allow_html') && $this->input_type === 'text') { $value = papi_maybe_json_decode(maybe_unserialize($value)); if (!is_string($value)) { $value = ''; } $value = wp_strip_all_tags($value); } return $value; }
/** * Cast string value to right value type. * * @param string $str * * @return mixed */ function papi_cast_string_value($str) { if (!is_string($str)) { return $str; } if (is_numeric($str)) { return $str == (int) $str ? (int) $str : (double) $str; } if ($str === 'true' || $str === 'false') { return $str === 'true'; } return papi_maybe_json_decode(maybe_unserialize($str)); }
/** * Get value that should be saved. * * @param array $options * * @throws InvalidArgumentException when option values not matching the expected value. * * @return mixed */ public function get_value(array $options = []) { if (!isset($options['post_id']) || !is_int($options['post_id'])) { throw new InvalidArgumentException('Missing `post_id` option. Should be int.'); } if (!isset($options['property']) || $options['property'] instanceof Papi_Core_Property === false) { throw new InvalidArgumentException('Missing `property` option. Should be instance of `Papi_Core_Property`.'); } if (!isset($options['slug']) || empty($options['slug'])) { $options['slug'] = $options['property']->get_slug(true); } if (!isset($options['value'])) { throw new InvalidArgumentException('Missing `value` option.'); } $value = $this->call_value($options['value']); $value = $this->update_value($options['property'], $value, $options['slug'], $options['post_id']); return papi_maybe_json_decode(maybe_unserialize($value)); }
/** * Change value after it's loaded from the database. * * @param mixed $value * @param string $slug * @param int $post_id * * @return mixed */ public function load_value($value, $slug, $post_id) { $value = maybe_unserialize($value); return papi_maybe_json_decode($value, $this->get_setting('multiple')); }
/** * Change value after it's loaded from the database. * * @param mixed $value * @param string $slug * @param int $post_id * * @return mixed */ public function load_value($value, $slug, $post_id) { $value = maybe_unserialize($value); return papi_maybe_json_decode($value, $this->convert_type === 'array'); }
/** * Get results from the database. * * @param int $value * @param string $repeater_slug * @param int $post_id * * @return array */ protected function get_results($value, $repeater_slug, $post_id) { global $wpdb; if ($this->is_option_page()) { $table = $wpdb->prefix . 'options'; $query = $wpdb->prepare("SELECT * FROM `{$table}` WHERE `option_name` LIKE '%s' ORDER BY `option_id` ASC", $repeater_slug . '_%'); } else { $table = sprintf('%s%smeta', $wpdb->prefix, $this->get_meta_type()); $column = papi_get_meta_id_column($this->get_meta_type()); $query = $wpdb->prepare("SELECT * FROM `{$table}` WHERE `meta_key` LIKE '%s' AND `{$column}` = %s ORDER BY `meta_id` ASC", $repeater_slug . '_%', $post_id); } $dbresults = $wpdb->get_results($query); $value = intval($value); // Do not proceed with empty value or columns. if (empty($value)) { return [[], []]; } $values = []; $results = []; $trash = []; // Get row results. $rows = $this->get_row_results($dbresults); // Get columns, divde all items with two. $columns = array_map(function ($row) { return count($row) / 2; }, $rows); $rows = array_values($rows); // Add repeater slug with number of rows to the values array. $values[$repeater_slug] = $value; for ($i = 0; $i < $value; $i++) { $no_trash = []; if (!isset($columns[$i]) || !isset($rows[$i])) { continue; } foreach ($rows[$i] as $slug => $meta) { if (!is_string($slug) || !isset($rows[$i][$slug])) { continue; } // Do not deal with layout meta object here since the property meta object will deal with it later. if (is_string($meta->meta_value) && preg_match($this->layout_value_regex, $meta->meta_value)) { if (!isset($values[$slug])) { $values[$slug] = $meta->meta_value; } continue; } // Add meta object to the no trash array. // so it won't be deleted. $no_trash[$slug] = $meta; // Serialize value if needed. $meta->meta_value = papi_maybe_json_decode(maybe_unserialize($meta->meta_value)); // Add property value and property type value. $values[$meta->meta_key] = $meta->meta_value; if (isset($rows[$i][$slug])) { // Add the meta value. $values[$slug] = $rows[$i][$slug]->meta_value; } } // Get the meta keys to delete. $trash_diff = array_diff(array_keys($rows[$i]), array_keys($no_trash)); if (!empty($trash_diff)) { // Find all trash meta objects from results array. foreach ($trash_diff as $slug) { if (!isset($results[$i]) || !isset($rows[$i][$slug])) { continue; } $trash[$results[$i][$slug]->meta_key] = $rows[$i][$slug]; } } } // Fetch one layout per row. // Since 3.0.0 this is backward compatibility. $dblayouts = []; foreach (array_keys($values) as $slug) { if ($this->is_layout_key($slug)) { $num = str_replace($repeater_slug . '_', '', $slug); $num = explode('_', $num); $num = intval($num[0]); if (!isset($dblayouts[$num])) { $dblayouts[$num] = $num . $values[$slug]; } } } $layouts = $this->get_settings_layouts(); // Add empty rows that isn't saved to database. for ($i = 0; $i < $value; $i++) { foreach ($layouts as $layout) { $layout_slug = sprintf('%s_%d%s', $this->get_slug(true), $i, $this->layout_key); // Since 3.0.0 the `$dblayouts` check is only for backward compatibility. if (isset($layout['slug']) && (isset($values[$layout_slug]) || in_array($i . $layout['slug'], $dblayouts, true))) { foreach ($layout['items'] as $prop) { $slug = sprintf('%s_%d_%s', $repeater_slug, $i, unpapify($prop->slug)); if (!isset($values[$slug])) { $values[$slug] = null; } } } } } return [$values, $trash]; }
/** * Update value before it's saved to the database. * * @param mixed $values * @param string $repeater_slug * @param int $post_id * * @return array */ public function update_value($values, $repeater_slug, $post_id) { $rows = intval(papi_get_property_meta_value($post_id, $repeater_slug)); if (!is_array($values)) { $values = []; } list($results, $trash) = $this->get_results($rows, $repeater_slug, $post_id); // Delete trash values. foreach ($trash as $meta) { papi_delete_property_meta_value($post_id, $meta->meta_key); } $values = papi_to_property_array_slugs($values, $repeater_slug); foreach ($values as $slug => $value) { if (papi_is_property_type_key($slug)) { continue; } $property_type_slug = papi_get_property_type_key_f($slug); if (!isset($values[$property_type_slug])) { continue; } // Get real property slug $property_slug = $this->get_child_slug($repeater_slug, $slug); // Get property type $property_type_value = $values[$property_type_slug]->type; $property_type = papi_get_property_type($property_type_value); // Unserialize if needed. $value = papi_maybe_json_decode(maybe_unserialize($value)); // Run update value on each property type class. $value = $property_type->update_value($value, $property_slug, $post_id); // Run update value on each property type filter. $values[$slug] = papi_filter_update_value($property_type_value, $value, $property_slug, $post_id, papi_get_meta_type()); if (is_array($values[$slug])) { foreach ($values[$slug] as $key => $val) { if (!is_string($key)) { continue; } unset($values[$slug][$key]); $key = preg_replace('/^\\_/', '', $key); $values[$slug][$key] = $val; } } } // Find out which keys that should be deleted. $trash = array_diff(array_keys(papi_to_array($results)), array_keys(papi_to_array($values))); // Delete unwanted (trash) values. foreach (array_keys($trash) as $trash_key) { papi_delete_property_meta_value($post_id, $trash_key); } // It's safe to remove all rows in the database here. $this->remove_repeater_rows($post_id, $repeater_slug); // Remove unnecessary property type keys if any is left. foreach (array_keys($values) as $slug) { if (papi_is_property_type_key($slug)) { unset($values[$slug]); } } return $values; }
/** * Sort the values on update. * * @param mixed $values * @param string $slug * @param int $post_id * * @return string */ public function update_value($values, $slug, $post_id) { $values = $this->format_value($values, $slug, $post_id); $values = array_map(function ($item) { if ($item instanceof WP_Post) { $item = $this->convert_post_to_item($item); } if (isset($item->title)) { unset($item->title); } return $item; }, $values); return papi_maybe_json_decode($values); }
/** * Change value after it's loaded from the database. * * @param mixed $values * @param string $slug * @param int $post_id * * @return mixed */ public function load_value($values, $slug, $post_id) { $values = (array) papi_maybe_json_decode(maybe_unserialize($values), true); return array_map('papi_maybe_convert_to_object', $values); }