/**
  * 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];
 }
 /**
  * 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.
     if (empty($value)) {
         return [[], []];
     }
     $values = [];
     $results = [];
     $trash = [];
     // Get row results.
     $rows = array_values($this->get_row_results($dbresults));
     // 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($no_trash[$i])) {
             $no_trash[$i] = [];
         }
         if (!isset($rows[$i])) {
             continue;
         }
         foreach ($rows[$i] as $slug => $meta) {
             if (!is_string($slug) || !isset($rows[$i][$slug])) {
                 continue;
             }
             // Add meta object to the no trash array.
             // so it won't be deleted.
             $no_trash[$slug] = $meta;
             // Add property value.
             $values[$meta->meta_key] = papi_maybe_json_decode(maybe_unserialize($meta->meta_value));
         }
         // Get the meta keys to delete.
         $trash_diff = array_diff(array_keys($rows[$i]), array_keys($no_trash[$i]));
         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];
             }
         }
     }
     $properties = $this->get_settings_properties();
     // Add empty rows that isn't saved to database.
     for ($i = 0; $i < $value; $i++) {
         foreach ($properties as $prop) {
             if (!isset($prop->slug)) {
                 continue;
             }
             $slug = sprintf('%s_%d_%s', $repeater_slug, $i, unpapify($prop->slug));
             if (!isset($values[$slug])) {
                 $values[$slug] = null;
             }
         }
     }
     return [$values, $trash];
 }