Manage Custom Tables';
return $links;
}
/**
* Format value before saving in DB
* @param $value
* @return string
*/
public function acf_ct_filter_format_value($value)
{
return $value;
}
public function acf_ct_filter_load_field($field)
{
/**
* Make fields read only if 'acf_ct_read_only_field' is true and current use is not a admin or
* 'acf_ct/edit_read_only_field' filter returns false
*/
if (array_key_exists('acf_ct_read_only_field', $field) && $field['acf_ct_read_only_field'] === 1) {
$field_details = array(
'key' => $field['key'],
'name' => $field['name'],
);
$edit_read_only_field = current_user_can('administrator') === true;
$edit_read_only_field = apply_filters('acf_ct/edit_read_only_field', $edit_read_only_field, $field_details);
if ($edit_read_only_field === false) {
$field['disabled'] = 1;
}
}
return $field;
}
public function acf_ct_filter_load_value($value, $post_id, $field)
{
/**
* Load only in admin
*/
// not required as user can load form on frontend
/*if (is_admin() === false) {
return $value;
}*/
$acfGroupKey = $field['parent'];
if (array_key_exists($acfGroupKey, self::$field_key_to_group_key_map)) {
$acfGroupKey = self::$field_key_to_group_key_map[$acfGroupKey];
} else if (array_key_exists($field['key'], self::$field_key_to_group_key_map)) {
$acfGroupKey = self::$field_key_to_group_key_map[$field['key']];
}
/**
* Set data from custom table
*/
$acfCtDBInstance = $this->get_acf_ct_table_class_instance($acfGroupKey, $post_id);
if (!$acfCtDBInstance instanceof Acfct_table_data) {
$acfCtDBInstance = $this->get_acf_ct_table_class_instance(self::$lastAcfGroupKey, $post_id);
} else {
self::$lastAcfGroupKey = $acfGroupKey;
}
if ($acfCtDBInstance instanceof Acfct_table_data) {
self::$field_key_to_group_key_map[$field['key']] = $acfGroupKey;
$db_value = $acfCtDBInstance->get($field['key'], $field['name']);
if (is_null($db_value) === false) {
return $db_value;
}
}
return $value;
}
public function acf_ct_handle_save_post($post_id)
{
// Bail early if no data sent.
if (empty($_POST['acf'])) {
return;
}
$acfArr = wp_kses_post_deep($_POST['acf']);
/**
* Get acf groups of current post
*/
$acf_groups = Acfct_utils::acf_get_field_groups_id($post_id);
$formatted_post_id = Acfct_utils::format_post_id($post_id);
if (empty($acf_groups)) {
return;
}
foreach ($acf_groups as $acf_post_id) {
$custom_table = Acfct_utils::get_custom_table_name($acf_post_id, true);
if ($custom_table === false) {
continue; //Custom table is not enabled
}
if (Acf_ct_database_manager::check_table_exists($custom_table) === false) {
continue; //Custom table is not exists
}
$store_acf_values_in_post_meta = apply_filters('acf_ct/settings/store_acf_values_in_post_meta', true);
$acfKeyMap = Acfct_utils::get_acf_keys($acf_post_id, true);
$dbHandler = new Acfct_table_data($formatted_post_id, $custom_table);
$columns = $dbHandler->getColumns();
$group_parent_keys = array();
$flat_post_array = array();
foreach (wp_unslash($acfArr) as $key => $value) {
$field_type = null;
if (array_key_exists($key, $acfKeyMap)) {
$field_type = $acfKeyMap[$key]['type'];
}
if (is_array($value) && $field_type === 'group') {
/**
* Create group_field_key => group_key map
* This map is used to unset group values
*/
foreach ($value as $sub_key => $field) {
$group_parent_keys[$sub_key] = $key;
}
/**
* Check group field types
* For flexible_content field type
* - Convert it into formatted value and unset it's key from group array
*/
foreach ($value as $group_field_key => $group_field) {
$group_field_type = null;
if (array_key_exists($group_field_key, $acfKeyMap)) {
$group_field_type = $acfKeyMap[$group_field_key]['type'];
}
if ($group_field_type === 'flexible_content' || $group_field_type === 'repeater') {
$flat_post_array[$group_field_key] = $this->get_formatted_value($group_field_type, $acfKeyMap, $group_field_key, $group_field);
unset($value[$group_field_key]); //unset field from group
}
}
/**
* Merge group fields with flat_array
*/
$flat_post_array = array_merge($flat_post_array, $value);
} else {
$flat_post_array[$key] = $this->get_formatted_value($field_type, $acfKeyMap, $key, $value);
}
}
$dbArray = array();
foreach ($flat_post_array as $key => $value) {
if (array_key_exists($key, $acfKeyMap) === false) {
continue;
}
$config = $acfKeyMap[$key];
if (in_array($config['name'], $columns)) {
$dbValue = apply_filters('acf_ct/format_value', $value);
$dbValue = apply_filters('acf_ct/format_value/' . $custom_table, $dbValue);
$dbValue = apply_filters('acf_ct/format_value/' . $custom_table . '/column=' . $config['name'], $dbValue);
$dbArray[$config['name']] = $dbValue;
if ($store_acf_values_in_post_meta == false) {
unset($_POST['acf'][$key]);
}
/**
* Unset group wrappers
*/
if (array_key_exists($key, $group_parent_keys) && $store_acf_values_in_post_meta == false) {
unset($_POST['acf'][$group_parent_keys[$key]]);
}
}
}
/**
* Save data only if acf values are updated
* @Note: To stop data from saving in post_meta, '_acf_changed' check added after unseting $_POST.
*/
if ($_POST['_acf_changed'] === "1" || $this->should_save_data()) {
$dbArray = apply_filters('acf_ct/update_table_data', $dbArray, $formatted_post_id, $custom_table);
$dbArray = apply_filters('acf_ct/update_table_data/name='.$custom_table, $dbArray, $formatted_post_id);
$dbHandler->saveData($dbArray);
}
}
}
/**
* @return bool
*/
public function should_save_data() {
// For attachment ajax request `_acf_changed` is always 0 so update.
if (wp_doing_ajax() && isset($_POST['_acf_screen']) && $_POST['_acf_screen'] === 'attachment') {
return true;
}
return false;
}
public function acf_ct_show_database_update_notice()
{
$change_list = false;
$customTableName = null;
if (get_post_type() === "acf-field-group" && isset($_GET['message'])) {
$change_list = Acf_ct_database_manager::get_acf_fields_change_list(get_the_ID());
}
if ($change_list !== false && $change_list['should_update'] === true) {
global $wpdb;
$customTableName = Acfct_utils::get_custom_table_name(get_the_ID());
$validate = Acf_ct_database_manager::validate_acf_group(get_the_ID());
?>
Table Name: prefix . $customTableName); ?>
| Changes: | ';
if (empty($change_list['added']) === false) {
echo '';
echo '| New columns: | ';
echo '' . Acfct_utils::get_span_tags_from_array($change_list['added']) . ' | ';
echo '
';
}
if (empty($change_list['updated']) === false) {
echo '';
echo '| Updated columns: | ';
echo '' . Acfct_utils::get_span_tags_from_array($change_list['updated']) . ' | ';
echo '
';
}
if (empty($change_list['deleted']) === false) {
echo '';
echo '| Deleted columns: | ';
echo '' . Acfct_utils::get_span_tags_from_array($change_list['deleted']) . ' | ';
echo '
';
}
}
?>
To apply these updates to your custom table, you need to run the update process on the Manage Tables screen.
">Go to Manage Tables
1) {
echo '
MySQL reserved keywords ' . Acfct_utils::get_span_tags_from_array($validate['invalid_columns']) . ' are not allowed as a column name
';
} else {
echo '
MySQL reserved keyword ' . Acfct_utils::get_span_tags_from_array($validate['invalid_columns']) . ' is not allowed as a column name
';
}
}
if (empty($validate['duplicate_columns']) === false) {
$duplicate_columns = "";
foreach ($validate['duplicate_columns'] as $column) {
$duplicate_columns .= "
$column";
}
echo '
Duplicate field names found: ' . wp_kses($duplicate_columns, ['span' => ['style'=>[], 'class'=>[]]]) . ' Please use unique name.
';
}
?>
is_table_data_fetched($acf_field_group_key)) {
return $GLOBALS[$key];
}
$acf_field_groups = Acfct_utils::get_acf_field_groups_meta($post_id);
foreach ($acf_field_groups as $field_group) {
$table_name = $field_group['table'];
$acf_post_id = $field_group['id'];
if ($this->is_table_data_fetched($field_group['key'])) {
continue;
}
$tableInstance = new Acfct_table_data(Acfct_utils::format_post_id($post_id), $table_name);
$tableInstance->fetchValues($acf_post_id);
$GLOBALS['acf_ct_loaded_' . $field_group['key']] = $tableInstance;
/**
* For non-local json mode, field parent is field_group id.
*/
$GLOBALS['acf_ct_loaded_' . $field_group['id']] = $tableInstance;
}
// if null then that means group is not present. ACF field group is not present in the DB.
return array_key_exists($key, $GLOBALS) ? $GLOBALS[$key] : null;
}
public function acf_ct_field_group_custom_table_settings()
{
add_meta_box('acf-field-group-custom-table-settings', ACF_CT_PLUGIN_NAME, function () {
include_once ACF_CUSTOM_TABLE_PATH . 'includes/views/acf-field-group-settings.php';
}, 'acf-field-group', 'normal');
}
/**
* Load custom js on acf setting page
*/
public function acf_ct_inject_custom_js()
{
?>
field_type
*/
$acf_ct_field_type_map[$field['ID']] = $field['type'];
/**
* List of types for which exclude column setting will not be shown
*/
$blacklisted_parent_types = array('flexible_content', 'repeater');
$blacklisted_field_types = array('group', 'message', 'accordion', 'tab');
/**
* Exclude column settings
*/
if (in_array($field['type'], $blacklisted_field_types) === false && in_array($parent_type, $blacklisted_parent_types) === false) {
acf_render_field_setting($field, array(
'label' => 'Exclude Column?',
'instructions' => 'The column will not be created in custom table and data will be saved in post meta',
'name' => 'acf_ct_exclude_column',
'type' => 'true_false',
'ui' => 1,
), true);
}
/**
* Read only settings
*/
$blacklisted_read_only_parent_types = array('flexible_content', 'repeater');
$blacklisted_read_only_field_types = array('group', 'message', 'accordion', 'tab', 'flexible_content',
'repeater', 'gallery', 'file', 'wysiwyg', 'radio',
'checkbox', 'button_group', 'link', 'relationship', 'taxonomy',
'date_time_picker', 'time_picker', 'color_picker', 'image', 'true_false');
if (in_array($field['type'], $blacklisted_read_only_field_types) === false && in_array($parent_type, $blacklisted_read_only_parent_types) === false) {
acf_render_field_setting($field, array(
'label' => 'Read Only',
'instructions' => 'Only Administrator can edit this field. Other role users can only view the field.',
'name' => 'acf_ct_read_only_field',
'type' => 'true_false',
'ui' => 1
), true);
}
}
/**
* Delete custom table row on post deleted
* @param $post_id
*/
public function delete_custom_table_row($post_id)
{
$custom_tables = Acfct_utils::get_custom_table_names_of_post($post_id);
if (empty($custom_tables) === true) {
return;
}
global $wpdb;
/**
* Delete row of custom table where post_id = $post_id
*/
foreach ($custom_tables as $custom_table) {
$delete_query = 'DELETE FROM ' . $custom_table . ' WHERE ' . ACF_CUSTOM_TABLE_POST_ID_COLUMN . ' = "' . $post_id . '"';
$wpdb->query($delete_query);
}
}
public function acf_ct_filter_pre_load_value($value, $post_id = false, $field = array())
{
$is_get_field_support_disabled = apply_filters('acf_ct/settings/disable_get_field_support', false);
if (is_admin() === true || $is_get_field_support_disabled === true) {
return null;
}
$selector = $field['name'];
$columns = $this->get_columns_map($post_id);
if (empty($columns) === true) {
return null;
}
/**
* Check whether column exists for selector
*/
$column_meta = array_filter($columns, function ($column) use ($selector) {
return $column['name'] === $selector;
});
/**
* return null if column not exists
*/
if (empty($column_meta)) {
return null;
}
/**
* Fetch data from db
*/
$table = current($column_meta)['table'];
$data = get_custom_table_fields($table, false, $post_id);
if (is_array($data) && array_key_exists($selector, $data)) {
return acf_ct_unserialize($data[$selector]);
}
return null;
}
public function acf_ct_filter_pre_update_value($check, $value, $post_id, $field)
{
$is_update_field_support_disabled = apply_filters('acf_ct/settings/disable_update_field_support', false);
if (
// if update field support is disabled
$is_update_field_support_disabled === true ||
// if current request is post update request
(is_admin() === true && $_SERVER['REQUEST_METHOD'] === 'POST' && $_REQUEST['action'] === 'editpost') ||
// if current request is ACF frontend form update request
($_SERVER['REQUEST_METHOD'] === 'POST' && $_REQUEST['_acf_screen'] === 'acf_form')
) {
return null;
}
$selector = $field['name'];
$columns = $this->get_columns_map($post_id);
if (empty($columns) === true) {
return null;
}
/**
* Check whether column exists for selector
*/
$column_meta = array_filter($columns, function ($column) use ($selector) {
return $column['name'] === $selector;
});
/**
* return null if column not exists
*/
if (empty($column_meta)) {
return null;
}
$table = current($column_meta)['table'];
return update_custom_table_field($table, [$selector => $value], $post_id);
}
/**
* Add column in field group table
*
* @param $columns
* @return mixed
*/
public function acf_ct_field_group_columns($columns)
{
$columns['acf-ct-table-name'] = __('Custom Table');
return $columns;
}
/**
* Render field group column data
*
* @param $column
* @param $post_id
*/
public function acf_ct_field_group_column_html($column, $post_id)
{
if ($column === 'acf-ct-table-name') {
$tableName = Acfct_utils::get_custom_table_name($post_id, true);
if (empty($tableName)) {
echo "-";
return;
}
$url = Acfct_utils::get_manage_table_page_url($post_id);
$status = Acf_ct_database_manager::get_acf_fields_change_list($post_id);
$label = false;
if (is_array($status)) {
if (array_key_exists('created', $status) && $status['created'] === true) {
$label = 'Create Table';
} else if (array_key_exists('should_update', $status) && $status['should_update'] === true) {
$label = 'Update Table';
}
}
echo ''. esc_html($tableName) . '';
if ($label !== false) {
echo ' - ' . esc_html($label) . '';
}
}
}
protected function get_columns_map($post_id)
{
/**
* Get all field groups associated with $post_id
*/
$acf_field_groups = Acfct_utils::get_acf_field_groups_meta($post_id);
if (empty($acf_field_groups)) {
return array();
}
/**
* Create map of columns and their table name
*/
$columns = array();
/*
* Check for cache
*/
$columns_meta_cache_key = "acf_ct:$post_id:columns_meta";
$columns_meta = wp_cache_get($columns_meta_cache_key);
if ($columns_meta === false) {
foreach ($acf_field_groups as $field_group) {
$fields = Acfct_utils::get_acf_keys($field_group['id']);
$table_name = $field_group['table'];
$columns_meta = array_reduce($fields, function ($column_data, $field) use ($table_name) {
$column_data[$field['key']] = array(
'name' => $field['name'],
'key' => $field['key'],
'table' => $table_name
);
return $column_data;
}, array());
$columns = array_merge($columns, $columns_meta);
}
wp_cache_set($columns_meta_cache_key, $columns); //save in cache
} else {
$columns = $columns_meta; //cached value
}
return $columns;
}
protected function is_table_data_fetched($acfFieldGroupKey)
{
$key = 'acf_ct_loaded_' . $acfFieldGroupKey;
return array_key_exists($key, $GLOBALS) && $GLOBALS[$key] instanceof Acfct_table_data;
}
}
new Acf_ct_register_hooks();