/** * 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; }
/** * Render repeater row. */ protected function render_repeater_row() { $layouts = $this->get_settings_layouts(); $values = $this->get_value(); // Fetch all slugs in all layouts. $slugs = []; foreach ($layouts as $index => $layout) { foreach ($layout['items'] as $item) { $slugs[] = unpapify($item->slug); } } // Remove values that don't exists in the slugs array. foreach ($values as $index => $row) { $keys = array_keys($row); foreach (array_keys($row) as $slug) { if (in_array($slug, $keys, true) || papi_is_property_type_key($slug) || $this->is_layout_key($slug)) { continue; } unset($values[$index][$slug]); } } $values = array_filter($values); $closed_rows = $this->get_setting('closed_rows', true); foreach ($values as $index => $row) { ?> <tr <?php echo $closed_rows ? 'class="closed"' : ''; ?> > <td class="handle"> <span class="toggle"></span> <span class="count"><?php echo esc_html($this->counter + 1); ?> </span> </td> <?php foreach ($layouts as $layout) { // Don't render layouts that don't have a valid value in the database. if (!isset($row[$this->layout_key]) || $layout['slug'] !== $this->get_layout_value($row[$this->layout_key])) { continue; } // Render all properties in the layout $this->render_properties($layout['items'], $row); } $this->counter++; ?> <td class="last"> <span> <a title="<?php esc_html_e('Remove', 'papi'); ?> " href="#" class="repeater-remove-item">x</a> </span> </td> </tr> <?php } }
/** * 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; }
/** * Convert array of arrays to array of slugs. * The given slug will match a key with the number of properties. * * @param array $value * @param string $slug * * @return array */ function papi_to_property_array_slugs(array $value, $slug) { $results = []; $counter = []; foreach ($value as $index => $arr) { if (!is_array($arr)) { continue; } $counter[] = $arr; foreach ($arr as $key => $val) { if (!is_string($key) || empty($key)) { continue; } if ($key[0] !== '_') { $key = '_' . $key; } $item_slug = $slug . '_' . $index . $key; if (papi_is_property_type_key($item_slug)) { $item_slug = papi_f($item_slug); } $results[$item_slug] = $val; } } $results[$slug] = count($counter); return $results; }
/** * Prepare properties data for saving. * * @param array $data * @param int $post_id * * @return array */ protected function prepare_properties_data(array $data = [], $post_id = 0) { // Since we are storing witch property it is in the `$data` array // we need to remove that and set the property type to the property // and make a array of the property type and the value. foreach ($data as $key => $value) { if (papi_is_property_type_key($key)) { continue; } $property_type_key = papify(papi_get_property_type_key($key)); // Check if value exists. if (!isset($data[$key]) && !isset($data[$property_type_key])) { continue; } // Pair property value with property type object. $data[$key] = ['type' => $data[$property_type_key], 'value' => $value]; // Remove property type object since it's not needed anymore. unset($data[$property_type_key]); } foreach ($data as $key => $item) { if (papi_is_property_type_key($key)) { continue; } $property = papi_get_property_type($item['type']); unset($data[$key]); if (papi_is_property($property)) { // Run `update_value` method on the property class. $data[$key] = $property->update_value($item['value'], unpapify($key), $post_id); // Apply `update_value` filter so this can be changed from // the theme for specified property type. $data[$key] = papi_filter_update_value($item['type']->type, $data[$key], unpapify($key), $post_id, papi_get_meta_type()); if ($item['type']->overwrite) { $slug = unpapify($key); $this->overwrite[$slug] = $data[$key]; unset($data[$key]); } } } return $data; }