File: /mnt/HC_Volume_101697859/livrariaboanoite.com.br/wp-content/plugins/woobase/admin/src/Rest/ACF.php
<?php
namespace VendBase\Rest;
// Prevent direct access to this file
defined("ABSPATH") || exit();
/**
* Class ACF
*
* Creates new rest api to handle ACF requests
*/
class ACF
{
/**
* ACF constructor.
*/
public function __construct()
{
add_action("rest_api_init", ["VendBase\Rest\ACF", "register_acf_field"]);
}
/**
* Register a custom field to the product endpoint
*
* @return void
*/
public static function register_acf_field()
{
foreach (["product", "shop_order", "product_cat", "shop_coupon", "shop_subscription"] as $type) {
register_rest_field($type, "vendbase_acf", [
"get_callback" => ["VendBase\Rest\ACF", "include_acf_fields_in_api_response"],
"update_callback" => ["VendBase\Rest\ACF", "update_acf_fields"],
"schema" => null,
]);
}
}
/**
* Adds ACF fields to the products response
*
* @param object $response
* @param object $product
* @param object $request
*
* @return $response
*/
public static function include_acf_fields_in_api_response($object, $field_name, $request)
{
if (!current_user_can("manage_woocommerce") && !current_user_can("manage_options")) {
return null;
}
if (!function_exists("get_field_objects")) {
return null;
}
// Don't return ACF fields on list endpoints
if ($request->get_param("id") === null) {
return null;
}
// Determine if we're dealing with a post or a term
$is_term = get_term($object["id"]);
$object_id = $is_term ? $object["id"] : $request->get_param("id");
if ($is_term && $is_term->name == $object["name"]) {
$acf_object_type = "taxonomy";
$acf_object_name = $is_term->taxonomy;
} else {
$post_type = get_post_type($object_id);
$acf_object_type = "post_type";
$acf_object_name = $post_type === "shop_order_placehold" ? "shop_order" : $post_type;
}
$field_groups = acf_get_field_groups([
$acf_object_type => $acf_object_name,
]);
$field_objects = self::get_all_acf_field_objects($object_id, $field_groups, $is_term);
$groups_with_fields = [];
foreach ($field_groups as $group) {
$group_with_fields = [
"name" => $group["title"],
"id" => $group["ID"],
"fields" => [],
];
foreach ($field_objects as $field) {
if ($field["parent"] == $group["ID"]) {
$group_with_fields["fields"][] = $field;
}
}
$groups_with_fields[] = $group_with_fields;
}
return $groups_with_fields;
}
/**
* Retrieves all ACF field objects for a given object and field groups.
*
* @param int $object_id The ID of the object to get field values for.
* @param array $field_groups An array of field group identifiers.
* @param bool $is_term Whether the object is a term or not.
* @return array An associative array of all fields.
*/
private static function get_all_acf_field_objects($object_id, $field_groups, $is_term = false)
{
$all_fields = [];
foreach ($field_groups as $field_group) {
$fields = acf_get_fields($field_group);
foreach ($fields as $field) {
if ($is_term) {
$field["value"] = get_field($field["name"], "term_" . $object_id);
} else {
$field["value"] = get_field($field["name"], $object_id);
}
$all_fields[$field["name"]] = $field;
}
}
return $all_fields;
}
/**
* Updates ACF fields for a WooCommerce product, including groups and repeaters.
*
* @param array $fields The array of fields to update.
* @param WP_Post $object The WordPress post object.
* @param string $field_name The name of the field being updated.
* @param WP_REST_Request $request The current request object.
* @param string $post_type The post type of the object.
*
* @return bool|WP_Error True on success, WP_Error object on failure.
*/
public static function update_acf_fields($fields, $object, $field_name, $request, $post_type)
{
// Check user capabilities
if (!current_user_can("manage_woocommerce") && !current_user_can("manage_options")) {
return new \WP_Error("rest_cannot_update", __("Sorry, you are not allowed to update this item."), ["status" => rest_authorization_required_code()]);
}
// Ensure ACF functions are available
if (!function_exists("update_field")) {
return new \WP_Error("acf_not_available", __("Advanced Custom Fields plugin is not active or available."), ["status" => 500]);
}
$updated = true;
$is_term = false;
if (taxonomy_exists($post_type)) {
$is_term = true;
}
$object_id = $is_term ? $object->term_id : $object->get_id();
foreach ($fields as $group) {
foreach ($group["fields"] as $field) {
$update_result = self::update_field_recursive($field, $object_id, $is_term);
if ($update_result === false) {
$updated = false;
}
}
}
if ($updated) {
return true;
} else {
return new \WP_Error("acf_update_failed", __("Failed to update one or more ACF fields."), ["status" => 500]);
}
}
/**
* Recursively updates ACF fields, handling nested structures like groups and repeaters.
*
* @param array $field The field to update.
* @param int $post_id The ID of the post being updated.
* @return bool True on success, false on failure.
*/
private static function update_field_recursive($field, $object_id, $is_term)
{
$field_key = $field["key"];
$field_value = $field["value"];
// Handle different field types
switch ($field["type"]) {
case "group":
foreach ($field_value as $sub_field_key => $sub_field_value) {
$sub_field = acf_get_field($sub_field_key);
if ($sub_field) {
$sub_field["value"] = $sub_field_value;
if (!self::update_field_recursive($sub_field, $object_id, $is_term)) {
return false;
}
}
}
return true;
case "repeater":
if (!empty($field_value) && is_array($field_value)) {
$prefix = $is_term ? "term_" : "";
delete_field($field_key, $prefix . $object_id); // Clear existing repeater rows
foreach ($field_value as $row_index => $row) {
if ($is_term) {
// For taxonomies, we need to update the entire repeater field
$updated_value = get_field($field_key, $prefix . $object_id) ?: [];
$updated_value[] = $row;
if (!update_field($field_key, $updated_value, $prefix . $object_id)) {
return false;
}
} else {
// For post types, we can use update_row
if (!update_row($field_key, $row_index + 1, $row, $object_id)) {
return false;
}
}
}
}
return true;
default:
return $is_term ? update_field($field_key, $field_value, "term_" . $object_id) : update_field($field_key, $field_value, $object_id);
}
}
}