File: /var/www/clients/client1/web95/web/wp-content/plugins/wpai-acf-add-on/src/fields/Field.php
<?php
namespace wpai_acf_add_on\fields;
use wpai_acf_add_on\ACFService;
define('PMAI_FIELDS_ROOT_DIR', str_replace('\\', '/', dirname(__FILE__)));
/**
* Class Field
* @package wpai_acf_add_on\fields
*/
abstract class Field implements FieldInterface {
/**
* field type
*/
public $type;
/**
* @var array
*/
public $data;
/**
* @var bool
*/
public $supportedVersion = false;
/**
* @var array
*/
public $parsingData;
/**
* @var array
*/
public $importData;
/**
* @var array
*/
public $options = array();
/**
* @var Field
*/
public $parent;
/**
* @var array
*/
public $subFields = array();
/**
* Field constructor.
* @param $field
* @param $post
* @param $field_name
* @param $parent_field
*/
public function __construct($field, $post, $field_name = "", $parent_field = false) {
$this->data = array(
'field' => $field,
'post' => $post,
'field_name' => $field_name
);
$this->setParent($parent_field);
$this->data = array_merge($this->data, $this->getFieldData());
$this->initSubFields();
}
/**
* Create sub field instances
*/
public function initSubFields(){
// Get sub fields configuration
$subFieldsData = $this->isLocalFieldStorage() ? $this->getLocalSubFieldsData() : $this->getDBSubFieldsData();
if ($subFieldsData){
foreach ($subFieldsData as $subFieldData) {
$field = $this->initDataAndCreateField($subFieldData);
$this->subFields[] = $field;
}
}
// Init sub fields for Flexible Content
if (ACFService::isACFNewerThan('5.0.0') && $this->getType() == 'flexible_content' && $this->isLocalFieldStorage()) {
// get flexible field
$flexibleField = $this->getData('field');
// vars
$flex_fields = acf_get_fields($flexibleField);
// loop through layouts, sub fields and swap out the field key with the real field
foreach (array_keys($flexibleField['layouts']) as $fi) {
// extract layout
$layout = acf_extract_var($flexibleField['layouts'], $fi);
// append sub fields
if (!empty($flex_fields)) {
$layout['sub_fields'] = [];
foreach (array_keys($flex_fields) as $fk) {
// check if 'parent_layout' is empty
if (empty($flex_fields[$fk]['parent_layout'])) {
// parent_layout did not save for this field, default it to first layout
$flex_fields[$fk]['parent_layout'] = $layout['key'];
}
// append sub field to layout,
if ($flex_fields[$fk]['parent_layout'] == $layout['key']) {
$layout['sub_fields'][] = acf_extract_var($flex_fields, $fk);
}
}
}
// append back to layouts
$this->data['field']['layouts'][$fi] = $layout;
}
}
}
/**
* @return array
*/
private function getFieldData(){
$data = array();
$field = $this->getData('field');
$post = $this->getData('post');
// set field default values
$reset = array('multiple', 'class', 'id');
foreach ($reset as $key){
if (empty($field[$key])) $field[$key] = false;
}
if ( array_key_exists( 'key', $field ) ) {
$data['current_field'] = empty($post['fields'][$field['key']]) ? false : $post['fields'][$field['key']];
} else {
$data['current_field'] = false;
}
$options = array('is_multiple_field_value', 'multiple_value');
foreach ($options as $option){
$data['current_' . $option] = isset($field['key']) && isset($post[$option][$field['key']]) ? $post[$option][$field['key']] : false;
}
// If parent field exists, parse field name
if ( "" != $this->getData('field_name') ){
$field_keys = str_replace(array('[',']'), array(''), str_replace('][', ':', $this->getData('field_name')));
$data['current_field'] = false;
foreach (explode(":", $field_keys) as $n => $key) {
if (!empty($post['fields'][$key])) {
$data['current_field'] = $post['fields'][$key];
} elseif (isset($data['current_field'][$key])) {
$data['current_field'] = $data['current_field'][$key];
}
foreach ($options as $option){
if (!empty($post[$option][$key])) {
$data['current_' . $option] = $post[$option][$key];
} elseif(!empty($data['current_' . $option][$key])) {
$data['current_' . $option] = $data['current_' . $option][$key];
}
}
}
$data['current_field'] = empty($data['current_field'][$field['key']]) ? false : $data['current_field'][$field['key']];
foreach ($options as $option){
$data['current_' . $option] = isset($data['current_' . $option][$field['key']]) ? $data['current_' . $option][$field['key']] : false;
}
}
return $data;
}
/**
* @param $xpath
* @param $parsingData
* @param array $args
* @return void
*/
public function parse($xpath, $parsingData, $args = array()) {
$this->parsingData = $parsingData;
$defaults = array(
'field_path' => '',
'xpath_suffix' => '',
'repeater_count_rows' => 0,
'inside_repeater' => false
);
$args = array_merge($defaults, $args);
$field = $this->getData('field');
$isMultipleField = (isset($parsingData['import']->options['is_multiple_field_value'][$field['key']])) ? $parsingData['import']->options['is_multiple_field_value'][$field['key']] : FALSE;
$multipleValue = (isset($parsingData['import']->options['multiple_value'][$field['key']])) ? $parsingData['import']->options['multiple_value'][$field['key']] : FALSE;
if ("" != $args['field_path']) {
$fieldKeys = preg_replace('%[\[\]]%', '', str_replace('][', ':', $args['field_path']));
$is_multiple_field_value = $parsingData['import']->options['is_multiple_field_value'];
$is_multiple_value = $parsingData['import']->options['multiple_value'];
foreach (explode(":", $fieldKeys) as $n => $key) {
$xpath = (!$n) ? $parsingData['import']->options['fields'][$key] : $xpath[$key];
if (!$n && isset($is_multiple_field_value[$key])) {
$isMultipleField = $is_multiple_field_value[$key];
}
if (isset($isMultipleField[$key])) {
$isMultipleField = $isMultipleField[$key];
}
if (!$n && isset($is_multiple_value[$key])) {
$multipleValue = $is_multiple_value[$key];
}
if (isset($multipleValue[$key])) {
$multipleValue = $multipleValue[$key];
}
}
$xpath = empty($xpath[$field['key']]) ? false : $xpath[$field['key']];
$isMultipleField = isset($isMultipleField[$field['key']]) ? $isMultipleField[$field['key']] : false;
$multipleValue = isset($multipleValue[$field['key']]) ? $multipleValue[$field['key']] : false;
}
$this->setOption('base_xpath', $parsingData['xpath_prefix'] . $parsingData['import']->xpath . $args['xpath_suffix']);
$this->setOption('xpath', $xpath);
$this->setOption('is_multiple_field', $isMultipleField);
$this->setOption('multiple_value', $multipleValue);
$this->setOption('count', ($args['repeater_count_rows']) ? $args['repeater_count_rows'] : $parsingData['count']);
$this->setOption('values', array_fill(0, $this->getOption('count'), ""));
$this->setOption('field_path', $args['field_path']);
}
/**
* @param $importData
* @param array $args
* @return bool
*/
public function import($importData, $args = array()){
$defaults = array(
'container_name' => '',
'parent_repeater' => ''
);
$field = $this->getData('field');
$args = array_merge($defaults, $args);
$this->importData = array_merge($importData, $args);
$this->parsingData['logger'] and call_user_func($this->parsingData['logger'], sprintf(__('- Importing field `%s`', 'wp_all_import_acf_add_on'), $this->importData['container_name'] . $field['name']));
$parsedData = $this->getParsedData();
// If update is not allowed
if (!empty($this->importData['articleData']['ID']) && ! \pmai_is_acf_update_allowed($this->importData['container_name'] . $field['name'], $this->parsingData['import']->options, $this->parsingData['import']->id)) {
$this->parsingData['logger'] && call_user_func($this->parsingData['logger'], sprintf(__('- Field `%s` is skipped attempted to import options', 'wp_all_import_acf_add_on'), $this->getFieldName()));
return FALSE;
}
// Do not import empty fields.
if ( in_array($this->getType(), ['file', 'image', 'gallery']) ) {
$value = ( $this->isNotEmpty() ) ? true : '';
} else {
$value = $this->getFieldValue();
}
if ($value === '' && ! in_array($this->getType(), ['group', 'repeater', 'clone', 'flexible_content', 'button_group'])) {
$is_import_empty_acf_fields = apply_filters("wp_all_import_is_import_empty_acf_fields", true, $this->parsingData['import']->id);
if (empty($is_import_empty_acf_fields)) {
return FALSE;
}
}
switch ($this->getImportType()) {
case 'import_users':
case 'shop_customer':
update_user_meta($this->getPostID(), "_" . $this->getFieldName(), $this->getFieldKey());
break;
case 'taxonomies':
update_term_meta($this->getPostID(), "_" . $this->getFieldName(), $this->getFieldKey());
break;
default:
update_post_meta($this->getPostID(), "_" . $this->getFieldName(), $this->getFieldKey());
break;
}
return TRUE;
}
/**
* @param $importData
*/
public function saved_post($importData){}
/**
* Render field
*/
public function view() {
$this->renderHeader();
extract($this->data);
$fields = $this->getSubFields();
switch ($this->supportedVersion){
case 'v4':
case 'v5':
$fieldDir = PMAI_FIELDS_ROOT_DIR . '/views/'. $this->type;
$fieldDir = apply_filters( 'wp_all_import_acf_field_view_dir', $fieldDir, $this );
$fieldDir = apply_filters( 'wp_all_import_acf_field_view_dir_' . $this->type, $fieldDir, $this );
$filePath = $fieldDir . DIRECTORY_SEPARATOR . $this->type . '-' . $this->supportedVersion . '.php';
$filePath = apply_filters( 'wp_all_import_acf_field_view_path', $filePath, $this );
$filePath = apply_filters( 'wp_all_import_acf_field_view_path_' . $this->type, $filePath, $this );
if (is_file($filePath)) {
// Render field header.
$header = $fieldDir . DIRECTORY_SEPARATOR . 'header.php';
if (file_exists($header) && is_readable($header)) {
include $header;
}
// Render field.
include $filePath;
// Render field footer.
$footer = $fieldDir . DIRECTORY_SEPARATOR . 'footer.php';
if (file_exists($footer) && is_readable($footer)) {
include $footer;
}
}
break;
default:
$filePath = __DIR__ . '/views/'. $this->type .'.php';
$filePath = apply_filters( 'wp_all_import_acf_field_view_path', $filePath, $this );
$filePath = apply_filters( 'wp_all_import_acf_field_view_path_' . $this->type, $filePath, $this );
if (is_file($filePath)) {
include $filePath;
}
break;
}
$this->renderFooter();
}
/**
* Render field header
*/
protected function renderHeader(){
$filePath = __DIR__ . '/templates/header.php';
$filePath = apply_filters( 'wp_all_import_acf_field_template_header_path', $filePath, $this );
$filePath = apply_filters( 'wp_all_import_acf_field_template_header_path' . $this->type, $filePath, $this );
if (is_file($filePath)) {
extract($this->data);
include $filePath;
}
}
/**
* Render field footer
*/
protected function renderFooter(){
$filePath = __DIR__ . '/templates/footer.php';
$filePath = apply_filters( 'wp_all_import_acf_field_template_footer_path', $filePath, $this );
$filePath = apply_filters( 'wp_all_import_acf_field_template_footer_path' . $this->type, $filePath, $this );
if (is_file($filePath)) {
include $filePath;
}
}
/**
* @return mixed
*/
public function getType() {
return $this->type;
}
/**
* @return \wpai_acf_add_on\fields\Field|bool
*/
public function getParent() {
return $this->parent;
}
/**
* @param \wpai_acf_add_on\fields\Field|bool $parent
*/
public function setParent($parent) {
$this->parent = $parent;
}
/**
* @param $option
* @return bool|mixed
*/
public function getData($option){
return isset($this->data[$option]) ? $this->data[$option] : false;
}
/**
* @param $option
* @param $value
*/
public function setData($option, $value){
$this->data[$option] = $value;
}
/**
* @param $option
* @return bool|mixed
*/
public function getOption($option){
return isset($this->options[$option]) ? $this->options[$option] : false;
}
/**
* @param $option
* @param $value
*/
public function setOption($option, $value){
$this->options[$option] = $value;
}
/**
* @param $xpath
* @param string $suffix
*
* @return array
* @throws \XmlImportException
*/
public function getByXPath($xpath, $suffix = '') {
$values = array_fill(0, $this->getOption('count'), "");
if ($xpath != ""){
$file = false;
$values = \XmlImportParser::factory($this->parsingData['xml'], $this->getOption('base_xpath') . $suffix, $xpath, $file)->parse();
@unlink($file);
}
return $values;
}
/**
* @return mixed
*/
public function getParsingData() {
return $this->parsingData;
}
/**
* @return mixed
*/
public function getImportData() {
return $this->importData;
}
/**
* @return mixed
*/
public function getPostIndex(){
return $this->importData['i'];
}
/**
* @return mixed
*/
public function getPostID(){
return $this->importData['pid'];
}
/**
* @return string
*/
public function getFieldName(){
$fieldName = ( isset($this->data['field']['name']) ? $this->data['field']['name'] : '' );
if (empty($fieldName)) {
if (function_exists('acf_get_field')) {
$field = acf_get_field($this->data['field']['ID']);
} else {
$label = sanitize_title( $this->data['field']['label'] );
$fieldName = str_replace('-', '_', $label);
}
if (!empty($field)) {
$fieldName = $this->data['field']['name'] = $field['name'];
}
}
return !isset($this->importData['container_name']) ? $fieldName : $this->importData['container_name'] . $fieldName;
}
/**
* @param $fieldName
*/
public function setFieldInputName($fieldName){
$this->data['field_name'] = $fieldName;
$this->data = array_merge($this->data, $this->getFieldData());
}
/**
* @return string
*/
public function getFieldKey(){
return $this->data['field']['key'];
}
/**
* @return string
*/
public function getFieldLabel(){
return $this->data['field']['label'];
}
/**
* @return mixed
*/
public function getFieldValue(){
$values = $this->options['values'];
if (isset($this->options['is_multiple_field']) && $this->options['is_multiple_field'] == 'yes') {
$value = array_shift($values);
} else {
$value = isset($values[$this->getPostIndex()]) ? $values[$this->getPostIndex()] : '';
$parents = $this->getParents();
if (!empty($parents)){
foreach ($parents as $key => $parent) {
if ($parent['delimiter'] !== FALSE && !is_array($value)) {
$value = explode($parent['delimiter'], $value);
$value = isset($value[$parent['index']]) ? $value[$parent['index']] : '';
}
}
}
}
return $this->trimValue($value);
}
/**
* Trim
*
* @param $value
* @return array|string
*/
public function trimValue($value) {
if (is_array($value)) {
foreach ($value as $k => $v) {
if (is_string($v)) {
$value[$k] = $this->trimValue($v);
}
}
return $value;
}
return is_string($value) ? trim($value) : $value;
}
/**
* @param $option
* @return null|mixed
*/
public function getFieldOption($option){
return isset($this->data['field'][$option]) ? $this->data['field'][$option] : NULL;
}
/**
* @param $option
* @return null|mixed
*/
public function getImportOption($option){
$importData = $this->getImportData();
return isset($importData['import']->options[$option]) ? $importData['import']->options[$option] : NULL;
}
/**
* @return mixed
*/
public function getImportType(){
$importData = $this->getImportData();
return $importData['import']->options['custom_type'];
}
/**
* @return mixed
*/
public function getTaxonomyType(){
$importData = $this->getImportData();
return $importData['import']->options['taxonomy_type'];
}
/**
* @return mixed
*/
public function getLogger(){
return $this->parsingData['logger'];
}
/**
* @return array
*/
public function getSubFields(){
return $this->subFields;
}
/**
* @return bool
*/
public function isLocalFieldStorage(){
return !is_numeric($this->getFieldOption('ID')) || $this->getFieldOption('ID') == 0;
}
/**
* @return array
*/
public function getDBSubFieldsData(){
$fieldID = $this->getFieldOption('ID');
if (empty($fieldID)){
$fieldData = $this->getDBFieldDataByKey($this->getFieldKey());
if (!empty($fieldData['ID'])){
$fieldID = $fieldData['ID'];
}
}
$field = acf_get_field($fieldID);
if ( ! empty($field['sub_fields']) ) {
return $field['sub_fields'];
}
return [];
}
/**
* @return array
*/
public function getLocalSubFieldsData(){
$subFieldsData = array();
$subFields = $this->getFieldOption('sub_fields');
if (empty($subFields)){
if (ACFService::isACFNewerThan('5.0.0')) {
$fields = [];
if (function_exists('acf_local')) {
$fields = acf_local()->fields;
}
if (empty($fields) && function_exists('acf_get_local_fields')) {
$fields = acf_get_local_fields();
}
if (!empty($fields)) {
foreach ($fields as $field) {
if (isset($field['parent']) && $field['parent'] == $this->getFieldKey()) {
$subFieldData = $field;
$subFieldData['ID'] = $subFieldData['id'] = uniqid();
$subFieldsData[] = $subFieldData;
}
}
}
} else {
global $acf_register_field_group;
if (!empty($acf_register_field_group)){
foreach ($acf_register_field_group as $key => $group) {
foreach ($group['fields'] as $field) {
if (isset($field['parent']) && $field['parent'] == $this->getFieldKey()) {
$subFieldData = $field;
$subFieldData['ID'] = $subFieldData['id'] = uniqid();
$subFieldsData[] = $subFieldData;
}
}
}
}
}
} else {
foreach ($subFields as $field) {
$subFieldData = $field;
$subFieldData['ID'] = $subFieldData['id'] = uniqid();
$subFieldsData[] = $subFieldData;
}
}
return $subFieldsData;
}
/**
* @param $fieldKey
* @return \wpai_acf_add_on\fields\Field|bool
*/
public function getFieldByKey($fieldKey){
// Get field configuration
$fieldData = $this->isLocalFieldStorage() ? $this->getLocalFieldDataByKey($fieldKey) : $this->getDBFieldDataByKey($fieldKey);
return $fieldData ? $this->initDataAndCreateField($fieldData) : false;
}
/**
* @param $fieldKey
* @return bool
*/
protected function getLocalFieldDataByKey($fieldKey){
$fieldData = false;
$fields = [];
if (function_exists('acf_local')) {
$fields = acf_local()->fields;
}
if (empty($fields) && function_exists('acf_get_local_fields')) {
$fields = acf_get_local_fields();
}
if (!empty($fields)) {
foreach ($fields as $sub_field) {
if ($sub_field['key'] == $fieldKey) {
$fieldData = $sub_field;
$fieldData['ID'] = $fieldData['id'] = uniqid();
break;
}
}
}
return $fieldData;
}
/**
* @param $fieldKey
* @return array|bool|mixed
*/
protected function getDBFieldDataByKey($fieldKey){
return acf_get_field($fieldKey);
}
/**
* @param $subFieldData
* @return Field|bool
*/
public function initDataAndCreateField($subFieldData){
$fieldData = $subFieldData;
if (is_object($subFieldData)) {
$fieldData = empty($subFieldData->post_content) ? array() : unserialize($subFieldData->post_content);
$fieldData['ID'] = $fieldData['id'] = $subFieldData->ID;
$fieldData['label'] = $subFieldData->post_title;
$fieldData['key'] = $subFieldData->post_name;
$fieldData['name'] = $subFieldData->post_excerpt;
}
// Do not include same field as child to avoid `Maximum function nesting level` exception.
$parent = $this->getParent();
if ($parent) {
do {
if ( $parent->getFieldKey() == $fieldData['key'] ) {
return FALSE;
}
$parent = $parent->getParent();
} while ($parent);
}
if ( $this->getFieldKey() == $fieldData['key'] ) {
return FALSE;
}
// Create sub field instance
return FieldFactory::create($fieldData, $this->getData('post'), $this->getFieldName(), $this);
}
/**
* @return bool
*/
public function isNotEmpty() {
return (bool) $this->getCountValues();
}
/**
* @return int
*/
public function getCountValues($parentIndex = FALSE){
$parents = $this->getParents();
if ($parentIndex !== FALSE && isset($parents[$parentIndex])) {
$parents = [$parents[$parentIndex]];
}
$value = $this->getOriginalFieldValueAsString();
if (!empty($parents) && !$this->isEmptyValue($value) && !is_array($value)){
$parentIndex = false;
foreach ($parents as $key => $parent) {
if ($parentIndex !== false){
$value = $value[$parentIndex];
}
if ($parent['delimiter'] !== FALSE) {
$value = explode($parent['delimiter'], $value);
$parentIndex = $parent['index'];
}
}
}
return is_array($value) ? count($value) : !$this->isEmptyValue($value);
}
/**
*
* Helper function to detect is provided field is empty or not
*
* @param $value
* @return bool
*/
protected function isEmptyValue($value){
return ( is_null($value) || $value === false || $value === "");
}
/**
* @return mixed
*/
public function getOriginalFieldValueAsString(){
$values = $this->options['values'];
return isset($values[$this->getPostIndex()]) ? $values[$this->getPostIndex()] : '';
}
/**
* @return array
*/
protected function getParents(){
$field = $this;
$parents = array();
do{
$parent = $field->getParent();
if ($parent){
switch ($parent->type){
case 'repeater':
if ($parent->getMode() == 'fixed' || $parent->getMode() == 'csv' && $parent->getDelimiter()){
$parents[] = array(
'delimiter' => $parent->getDelimiter(),
'index' => $parent->getRowIndex()
);
}
break;
default:
break;
}
$field = $parent;
}
}
while($parent);
return array_reverse($parents);
}
/**
* @return array
*/
public function getParsedData(){
$field = $this->getData('field');
return array(
'type' => $field['type'],
'post_type' => isset($field['post_type']) ? $field['post_type'] : FALSE,
'name' => $field['name'],
'multiple' => isset($field['multiple']) ? $field['multiple'] : FALSE,
'values' => $this->getOption('values'),
'is_multiple' => $this->getOption('is_multiple'),
'is_variable' => $this->getOption('is_variable'),
'is_ignore_empties' => $this->getOption('is_ignore_empties'),
'xpath' => $this->getOption('xpath'),
'id' => empty($field['ID']) ? $field['id'] : $field['ID']
);
}
}