| | |
| | | <?php |
| | | namespace JVBase\meta; |
| | | |
| | | use JVBase\base\Options; |
| | | use JVBase\registrar\Registrar; |
| | | use WP_Post; |
| | | use WP_Term; |
| | |
| | | protected WP_Post|WP_Term|WP_User|false|null $wpObject; |
| | | protected int|string $ID; |
| | | protected MetaTypeManager $typeManager; |
| | | protected static array $instances = ['post' => [],'term' => [], 'user'=>[],'options'=>[]]; |
| | | protected static array $instances = ['post' => [],'term' => [], 'user'=>[],'option'=>[]]; |
| | | |
| | | protected array $defaults = ['post_thumbnail']; |
| | | /** |
| | |
| | | /** |
| | | * Create Meta instance for options |
| | | */ |
| | | public static function forOptions(?string $baseKey = 'ajv'): self |
| | | public static function forOptions(?string $baseKey = BASE): self |
| | | { |
| | | if (array_key_exists($baseKey, self::$instances['options'])) { |
| | | return self::$instances['options'][$baseKey]; |
| | | if (array_key_exists($baseKey, self::$instances['option'])) { |
| | | return self::$instances['option'][$baseKey]; |
| | | } |
| | | $new = new self($baseKey, 'options'); |
| | | self::$instances['options'][$baseKey] = $new; |
| | | $new = new self($baseKey, 'option'); |
| | | self::$instances['option'][$baseKey] = $new; |
| | | return $new; |
| | | } |
| | | /*************************************************************** |
| | | * Constructor |
| | | ***************************************************************/ |
| | | |
| | | public function __construct(int|string|null $id, string $type) |
| | | public function __construct(int|string|null $id, string $type, array $fields = []) |
| | | { |
| | | $this->validator = new Validator(); |
| | | $this->sanitizer = new Sanitizer(); |
| | | $this->typeManager = new MetaTypeManager(); |
| | | $this->type = $type; |
| | | $this->ID = $id; |
| | | $this->buildData($id, $type); |
| | | $this->buildData($id, $type, $fields); |
| | | } |
| | | |
| | | protected function buildData(int|string|null $id, string $type):void |
| | | protected function buildData(int|string|null $id, string $type, array $fields):void |
| | | { |
| | | $this->wpObject = match($type) { |
| | | 'post' => get_post($id), |
| | |
| | | default => null |
| | | }; |
| | | |
| | | |
| | | |
| | | $registrar = !is_null($this->slug) ? Registrar::getInstance($this->slug) : false; |
| | | $fields = $registrar ? $registrar->getFields() : []; |
| | | $fields = $registrar ? $registrar->getFields() : $fields; |
| | | |
| | | if ($this->type == 'option') { |
| | | $options = Options::getInstance(); |
| | | $fields = $options->getFields(); |
| | | } |
| | | $meta = match($type) { |
| | | 'post' => get_post_meta($id), |
| | | 'term' => get_term_meta($id), |
| | |
| | | } |
| | | $meta = array_map(fn($value) => maybe_unserialize($value[0]), $meta); |
| | | |
| | | |
| | | $this->fields = []; |
| | | |
| | | if (class_exists('WooCommerce') && $this->type === 'post' && $this->wpObject->post_type??'' === 'product') { |
| | | $fields['post_title'] = [ |
| | | 'type' => 'text', |
| | | 'label' => 'Title', |
| | | ]; |
| | | $fields['post_content'] = [ |
| | | 'type' => 'text', |
| | | 'label' => 'Content', |
| | | ]; |
| | | $fields['post_excerpt'] = [ |
| | | 'type' => 'text', |
| | | 'label' => 'Short Description', |
| | | ]; |
| | | $fields['post_id'] = [ |
| | | 'type' => 'text', |
| | | 'label' => 'ID', |
| | | ]; |
| | | |
| | | |
| | | $fields['_stock'] = [ |
| | | 'type' => 'number', |
| | | 'label' => 'Stock', |
| | | 'default' => null |
| | | ]; |
| | | $fields['_stock_status'] = [ |
| | | 'type' => 'select', |
| | | 'label' => 'Stock Status', |
| | | 'default' => 'instock', |
| | | 'options' => [ |
| | | 'instock' => 'In Stock', |
| | | 'outofstock' => 'Out of Stock', |
| | | 'onbackorder' => 'On Backorder' |
| | | ] |
| | | ]; |
| | | $fields['_price'] = [ |
| | | 'type' => 'text', |
| | | 'subtype' => 'number', |
| | | 'label' => 'Price' |
| | | ]; |
| | | |
| | | |
| | | $product = wc_get_product($id); |
| | | $fields['sku'] = [ |
| | | 'type' => 'text', |
| | | 'label' => 'SKU', |
| | | ]; |
| | | |
| | | $out = []; |
| | | if ($product && $product->is_type('variable')) { |
| | | $var = $product->get_children(); |
| | | $var = array_filter(array_map(function($v) { |
| | | return wc_get_product($v); |
| | | }, $var)); |
| | | |
| | | $title= $product->get_title(); |
| | | foreach ($var as $variation) { |
| | | $out[] = [ |
| | | 'id' => $variation->get_id(), |
| | | 'sku' => $variation->get_sku(), |
| | | 'title' => str_replace($title.' - ', '', $variation->get_name()), |
| | | 'price' => $variation->get_price(), |
| | | 'description'=> $variation->get_short_description(), |
| | | 'sale' => $variation->get_sale_price(), |
| | | 'img' => $variation->get_image_id(), |
| | | 'stock' => $variation->get_stock_quantity(), |
| | | 'stock_status' => $variation->get_stock_status() |
| | | ]; |
| | | } |
| | | } |
| | | if (!empty($out)) { |
| | | $this->fields['variations'] = new Field('variations', $out, [ |
| | | 'type' => 'repeater', |
| | | 'label' => 'Variations', |
| | | 'fields' => [ |
| | | 'id' => [ |
| | | 'type' => 'text', |
| | | 'subtype' => 'number', |
| | | 'label' => 'Variation ID', |
| | | ], |
| | | 'sku' => [ |
| | | 'type' => 'text', |
| | | 'label' => 'Stock Keeping Unit (SKU)' |
| | | ], |
| | | 'title' => [ |
| | | 'type' => 'text', |
| | | 'label' => 'Variation Title' |
| | | ], |
| | | 'price' => [ |
| | | 'type' => 'text', |
| | | 'subtype' => 'number', |
| | | 'label' => 'Variation Price' |
| | | ], |
| | | 'sale' => [ |
| | | 'type' => 'text', |
| | | 'subtype' => 'number', |
| | | 'label' => 'Sale Price', |
| | | ], |
| | | 'image' => [ |
| | | 'type' => 'text', |
| | | 'subtype' => 'number', |
| | | 'label' => 'Variation Image ID' |
| | | ], |
| | | 'stock' => [ |
| | | 'type' => 'text', |
| | | 'label' => 'Stock Quantity' |
| | | ], |
| | | 'stock_status' => [ |
| | | 'type' => 'text', |
| | | 'label' => 'Stock Status' |
| | | ] |
| | | ] |
| | | ]); |
| | | } |
| | | |
| | | |
| | | } |
| | | foreach ($fields as $fieldName => $config) { |
| | | $fieldName = jvbNoBase($fieldName); |
| | | if ($this->wpObject && property_exists($this->wpObject, $fieldName)) { |
| | | $value = ''; |
| | | if ($this->type === 'option') { |
| | | $value = get_option(BASE . $fieldName, $config['default'] ?? ''); |
| | | } else if ( |
| | | ($this->wpObject && property_exists($this->wpObject, $fieldName)) |
| | | || ($type === 'user' && $this->wpObject && property_exists($this->wpObject->data, $fieldName))) { |
| | | $config['wp'] = true; |
| | | $value = $this->wpObject->$fieldName; |
| | | } else if (in_array($fieldName, $this->defaults)) { |
| | | |
| | | } else if (in_array($fieldName, $this->defaults)) { |
| | | $config['wp'] = true; |
| | | switch ($fieldName) { |
| | | case 'post_thumbnail': |
| | |
| | | if (str_contains($name, ':')) { |
| | | return $this->getByPath($name); |
| | | } |
| | | // Group shortcut path |
| | | if (str_contains($name, '|')) { |
| | | [$parent, $child] = explode('|', $name, 2); |
| | | return $this->group($parent)->get($child); |
| | | } |
| | | if (!array_key_exists($name, $this->fields)) { |
| | | error_log('[Meta]::get Attempted to get unregistered field: '.$name); |
| | | return ''; |
| | | } |
| | | if (is_null($this->fields[$name])) { |
| | | error_log('[Meta]::get Field does not seem to be setup yet: '.$name); |
| | | return ''; |
| | | } |
| | | return $this->fields[$name]->get()??''; |
| | | } |
| | |
| | | return $this->setByPath($name, $value); |
| | | } |
| | | |
| | | // Group shortcut |
| | | if (str_contains($name, '|')) { |
| | | return $this->setGroup($name, $value, $autosave); |
| | | } |
| | | |
| | | $field = $this->fields[$name]??false; |
| | | if (!$field) { |
| | | error_log('No config found for field: '.$name); |
| | |
| | | 'post' => 'update_post_meta', |
| | | 'term' => 'update_term_meta', |
| | | 'user' => 'update_user_meta', |
| | | 'options', 'option' => 'update_option', |
| | | 'option' => 'update_option', |
| | | default => false, |
| | | }; |
| | | if (!$function) { |
| | |
| | | return false; |
| | | } |
| | | foreach ($custom as $field) { |
| | | $result = $function($this->ID, BASE.$field->name, $field->value); |
| | | if ($this->type === 'option') { |
| | | $result = update_option(BASE.$field->name, $field->value); |
| | | } else { |
| | | $result = $function($this->ID, BASE.$field->name, $field->value); |
| | | } |
| | | |
| | | if (!$result) { |
| | | error_log('Problem saving field: '.$field->name.' with value: '.print_r($field->value, true)); |
| | | } |
| | |
| | | 'post' => delete_post_meta($this->ID, BASE.$name), |
| | | 'term' => delete_term_meta($this->ID, BASE.$name), |
| | | 'user', 'integrations' => delete_user_meta($this->ID, BASE.$name), |
| | | 'options' => delete_option(BASE.$name), |
| | | 'option' => delete_option(BASE.$name), |
| | | default => false |
| | | }; |
| | | } |
| | |
| | | return new Repeater($this, $name); |
| | | } |
| | | |
| | | |
| | | protected function setByPath(string $path, mixed $value): self |
| | | { |
| | | error_log('Setting by path: '.$path.', with value: '.print_r($value, true)); |
| | | $parts = explode(':', $path, 3); |
| | | if (count($parts) !== 3) { |
| | | return $this; |
| | |
| | | return $this->repeater($repeaterName)->field((int) $rowIndex, $subField); |
| | | } |
| | | |
| | | |
| | | |
| | | public function group(string $name): Group |
| | | { |
| | | return new Group($this, $name); |
| | | } |
| | | |
| | | protected function setGroup(string $name, mixed $value, bool $autosave = true): self |
| | | { |
| | | $parent = strtok($name, '|'); |
| | | $child = str_replace($parent . '|', '', $name); |
| | | |
| | | $this->group($parent)->set($child, $value, $autosave); |
| | | return $this; |
| | | } |
| | | |
| | | // ───────────────────────────────────────────────────────────── |
| | | // Utility Methods |
| | | // ───────────────────────────────────────────────────────────── |
| | |
| | | return $this->contentType; |
| | | } |
| | | |
| | | public function item():Item |
| | | { |
| | | return $this->item; |
| | | } |
| | | |
| | | |
| | | // ───────────────────────────────────────────────────────────── |
| | | // Protected Helpers |