'Select', ]; if ($isWithPost) { $groupChoices[self::GROUP_POST] = '$Post$'; } $groups = $this->getGroups(); foreach ($groups as $group) { $groupId = $group['key']; $groupChoices[$groupId] = $group['title']; } return $groupChoices; } protected function getFieldChoices(bool $isWithPost = true, array $excludeTypes = []): array { $fieldChoices = []; if (! function_exists('acf_get_fields')) { return $fieldChoices; } $fieldChoices = [ '' => 'Select', ]; if ($isWithPost) { $fieldChoices = array_merge($fieldChoices, [ Field::createKey(self::GROUP_POST, Post::FIELD_TITLE) => 'Title', Field::createKey(self::GROUP_POST, Post::FIELD_TITLE_LINK) => 'Title with link', Field::createKey(self::GROUP_POST, Post::FIELD_EXCERPT) => 'Excerpt', Field::createKey(self::GROUP_POST, Post::FIELD_THUMBNAIL) => 'Thumbnail', Field::createKey(self::GROUP_POST, Post::FIELD_AUTHOR) => 'Author', Field::createKey(self::GROUP_POST, Post::FIELD_DATE) => 'Published date', Field::createKey(self::GROUP_POST, Post::FIELD_MODIFIED) => 'Modified date', Field::createKey(self::GROUP_POST, Post::FIELD_LINK) => 'Link', ]); } $supportedFieldTypes = $this->getFieldTypes(); $groups = $this->getGroups(); foreach ($groups as $group) { $fields = acf_get_fields($group); foreach ($fields as $groupField) { if (! in_array($groupField['type'], $supportedFieldTypes, true) || ($excludeTypes && in_array($groupField['type'], $excludeTypes, true))) { continue; } $fullFieldId = Field::createKey($group['key'], $groupField['key']); $fieldChoices[$fullFieldId] = $groupField['label'] . ' (' . $groupField['type'] . ')'; } } return $fieldChoices; } protected function getRepeaterChoices(array $excludeTypes = []): array { $repeaterChoices = [ '' => 'Select', ]; $supportedFieldTypes = $this->getFieldTypes(); $groups = $this->getGroups(); foreach ($groups as $group) { $fields = acf_get_fields($group); foreach ($fields as $groupField) { $subFields = (array)($groupField['sub_fields'] ?? []); if ('repeater' !== $groupField['type'] || ! $subFields) { continue; } foreach ($subFields as $subField) { // repeater in repeater is not allowed if (! in_array($subField['type'], $supportedFieldTypes, true) || 'repeater' === $subField['type'] || ($excludeTypes && in_array($subField['type'], $excludeTypes, true))) { continue; } $fullFieldId = Field::createKey( $group['key'], $groupField['key'], $subField['key'] ); $repeaterChoices[$fullFieldId] = $subField['label'] . ' (' . $subField['type'] . ')'; } } } return $repeaterChoices; } protected function getPostTypeChoices(): array { return get_post_types(); } protected function getImageSizes(): array { $imageSizeChoices = []; $imageSizes = get_intermediate_image_sizes(); foreach ($imageSizes as $imageSize) { $imageSizeChoices[$imageSize] = ucfirst($imageSize); } $imageSizeChoices['full'] = 'Full'; return $imageSizeChoices; } protected function getPostStatusChoices(): array { return get_post_statuses(); } protected function getTaxonomyChoices(): array { $taxChoices = [ '' => 'Select', ]; $taxonomies = get_taxonomies([], 'objects'); foreach ($taxonomies as $taxonomy) { $taxChoices[$taxonomy->name] = $taxonomy->label; } return $taxChoices; } protected function getTermChoices(): array { $termChoices = [ '' => 'Select', ]; $taxonomyNames = get_taxonomies([]); foreach ($taxonomyNames as $taxonomyName) { $terms = get_terms([ 'taxonomy' => $taxonomyName, 'hide_empty' => false, ]); foreach ($terms as $term) { $fullTaxId = TaxField::createKey($taxonomyName, $term->term_id); $termChoices[$fullTaxId] = $term->name; } } return $termChoices; } protected function setConditionalRulesForField(array $field, string $targetField, array $notEqualValues): array { $field['conditional_logic'] = []; foreach ($notEqualValues as $notEqualValue) { // using exactly AND rule (so all rules in one array) and '!=' comparison, // otherwise if there are no such fields the field will be visible $field['conditional_logic'][] = [ 'field' => $targetField, 'operator' => '!=', 'value' => $notEqualValue, ]; } return $field; } protected function setGroupSelectChoices(): void { add_filter( 'acf/load_field/name=' . Item::getAcfFieldName(Item::FIELD_GROUP), function (array $field) { $field['choices'] = $this->getGroupChoices(); return $field; } ); add_filter( 'acf/load_field/name=' . AcfCardData::getAcfFieldName(AcfCardData::FIELD_ORDER_BY_META_FIELD_GROUP), function (array $field) { $field['choices'] = $this->getGroupChoices(false); return $field; } ); add_filter( 'acf/load_field/name=' . MetaField::getAcfFieldName(MetaField::FIELD_GROUP), function (array $field) { $field['choices'] = $this->getGroupChoices(false); return $field; } ); } protected function setFieldSelectChoices(): void { add_filter( 'acf/load_field/name=' . Field::getAcfFieldName(Field::FIELD_KEY), function (array $field) { $field['choices'] = $this->getFieldChoices(); return $field; } ); add_filter( 'acf/load_field/name=' . RepeaterField::getAcfFieldName(RepeaterField::FIELD_KEY), function (array $field) { $field['choices'] = $this->getRepeaterChoices(); return $field; } ); add_filter( 'acf/load_field/name=' . AcfCardData::getAcfFieldName(AcfCardData::FIELD_ORDER_BY_META_FIELD_KEY), function (array $field) { $field['choices'] = $this->getFieldChoices(false); return $field; } ); add_filter( 'acf/load_field/name=' . MetaField::getAcfFieldName(MetaField::FIELD_FIELD_KEY), function (array $field) { $field['choices'] = $this->getFieldChoices(false); return $field; } ); } protected function setViewConditionalRules(): void { add_filter( 'acf/load_field/name=' . Field::getAcfFieldName(Field::FIELD_LINK_LABEL), function (array $field) { // using exactly the negative (excludeTypes) filter, // otherwise if there are no such fields the field will be visible $notLinkFields = $this->getFieldChoices(true, ['link', 'page_link', 'file',]); $field = $this->setConditionalRulesForField( $field, Field::getAcfFieldName(Field::FIELD_KEY), array_keys($notLinkFields) ); return $field; } ); add_filter( 'acf/load_field/name=' . Field::getAcfFieldName(Field::FIELD_IMAGE_SIZE), function (array $field) { // using exactly the negative (excludeTypes) filter, // otherwise if there are no such fields the field will be visible $notImageFields = $this->getFieldChoices(true, ['image',]); // post thumbnail should have this setting too unset($notImageFields[Field::createKey(self::GROUP_POST, Post::FIELD_THUMBNAIL)]); return $this->setConditionalRulesForField( $field, Field::getAcfFieldName(Field::FIELD_KEY), array_keys($notImageFields) ); } ); add_filter( 'acf/load_field/name=' . RepeaterField::getAcfFieldName(RepeaterField::FIELD_LINK_LABEL), function (array $field) { // using exactly the negative (excludeTypes) filter, // otherwise if there are no such fields the field will be visible $notLinkFields = $this->getRepeaterChoices(['link', 'page_link', 'file',]); return $this->setConditionalRulesForField( $field, RepeaterField::getAcfFieldName(RepeaterField::FIELD_KEY), array_keys($notLinkFields) ); } ); add_filter( 'acf/load_field/name=' . Item::getAcfFieldName(Item::FIELD_REPEATER_FIELDS_TAB), function (array $field) { // using exactly the negative (excludeTypes) filter, // otherwise if there are no such fields the field will be visible $notRepeaterFields = $this->getFieldChoices(true, ['repeater',]); return $this->setConditionalRulesForField( $field, Field::getAcfFieldName(Field::FIELD_KEY), array_keys($notRepeaterFields) ); } ); } protected function setCardChoices(): void { add_filter( 'acf/load_field/name=' . AcfCardData::getAcfFieldName(AcfCardData::FIELD_POST_TYPES), function (array $field) { $field['choices'] = $this->getPostTypeChoices(); return $field; } ); add_filter( 'acf/load_field/name=' . AcfCardData::getAcfFieldName(AcfCardData::FIELD_POST_STATUSES), function (array $field) { $field['choices'] = $this->getPostStatusChoices(); return $field; } ); add_filter( 'acf/load_field/name=' . TaxField::getAcfFieldName(TaxField::FIELD_TAXONOMY), function (array $field) { $field['choices'] = $this->getTaxonomyChoices(); return $field; } ); add_filter( 'acf/load_field/name=' . TaxField::getAcfFieldName(TaxField::FIELD_TERM), function (array $field) { $field['choices'] = $this->getTermChoices(); return $field; } ); } protected function setViewChoices(): void { add_filter( 'acf/load_field/name=' . Field::getAcfFieldName(Field::FIELD_IMAGE_SIZE), function (array $field) { $field['choices'] = $this->getImageSizes(); return $field; } ); } // Important! Use this wrapper to avoid recursion protected function getGroups(): array { if (! function_exists('acf_get_field_groups')) { return []; } $acfGroups = acf_get_field_groups(); // Important! To avoid recursion, otherwise within 'getChoices()' will be available the same group as the current // and this class will call 'acf_get_fields()' that will call 'getChoices()' $acfGroups = array_filter($acfGroups, function ($acfGroup) { $isPrivate = (bool)($acfGroup['private'] ?? false); $isOwn = 0 === strpos($acfGroup['key'], AcfGroup::GROUP_NAME_PREFIX); $isLocal = (bool)($acfGroup['local'] ?? false); return (! $isPrivate && ! $isOwn && ! $isLocal); }); return array_values($acfGroups); } public function setHooks(): void { $this->setGroupSelectChoices(); $this->setFieldSelectChoices(); $this->setViewConditionalRules(); $this->setViewChoices(); $this->setCardChoices(); } public function getGroupedFieldTypes(): array { return [ 'basic' => [ 'text', 'textarea', 'number', 'range', 'email', 'url', 'password', ], 'content' => [ 'image', 'file', 'wysiwyg', ], 'choice' => [ 'select', 'checkbox', 'radio', 'true_false', ], 'jquery' => [ 'date_picker', 'date_time_picker', 'time_picker', 'color_picker', ], 'relational' => [ 'link', 'page_link', ], ]; } public function getFieldTypes(): array { $fieldTypes = []; $groupedFieldTypes = $this->getGroupedFieldTypes(); foreach ($groupedFieldTypes as $group => $fields) { $fieldTypes = array_merge($fieldTypes, $fields); } return $fieldTypes; } }