Zend certified PHP/Magento developer

Custom Category fields duplicated

We had an issue where updates to a custom category_form.xml file were made that changed their placement on the page. When I reverted back to the way it should have been, I now get duplicated fields.

This happened when we upgraded from 2.4.1 to 2.4.5.

enter image description here

The promo fields are also getting duplicated, but I’m guessing whatever the issue is with the author fields will be the same.

/app/code/Vendor/CategoryAuthorProfile/view/adminhtml/ui_component/category_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> 
<fieldset name="product_listing_page">
<settings>
    <label translate="true">Product Listing Page (PLP) Setup</label>
    <collapsible>true</collapsible>
</settings>
<fieldset name="author_profile">
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="label" xsi:type="string" translate="true">Author Profile</item>
            <item name="collapsible" xsi:type="boolean">true</item>
            <item name="sortOrder" xsi:type="number">10</item>
        </item>
    </argument>
    <field name="is_profile_displayed">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="sortOrder" xsi:type="number">10</item>
                <item name="dataType" xsi:type="string">boolean</item>
                <item name="formElement" xsi:type="string">checkbox</item>
                <item name="label" xsi:type="string" translate="true">Do you want to display the author profile?</item>
                <item name="prefer" xsi:type="string">toggle</item>
                <item name="valueMap" xsi:type="array">
                    <item name="true" xsi:type="string">1</item>
                    <item name="false" xsi:type="string">0</item>
                </item>
                <item name="default" xsi:type="number">0</item>
                <item name="notice" xsi:type="string" translate="true">The Author Profile will display in the first two spots of the product grid.</item>
            </item>
        </argument>
    </field>
    <field name="author_profile_name">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="required" xsi:type="boolean">false</item>
                <item name="validation" xsi:type="array">
                    <item name="required-entry" xsi:type="boolean">false</item>
                </item>
                <item name="sortOrder" xsi:type="number">20</item>
                <item name="dataType" xsi:type="string">string</item>
                <item name="formElement" xsi:type="string">input</item>
                <item name="label" translate="true" xsi:type="string">Author Name</item>
            </item>
        </argument>
    </field>
    <field name="author_profile_title">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="required" xsi:type="boolean">false</item>
                <item name="validation" xsi:type="array">
                    <item name="required-entry" xsi:type="boolean">false</item>
                </item>
                <item name="sortOrder" xsi:type="number">30</item>
                <item name="dataType" xsi:type="string">string</item>
                <item name="formElement" xsi:type="string">input</item>
                <item name="label" translate="true" xsi:type="string">Author Title</item>
            </item>
        </argument>
    </field>
    <field name="author_profile_bio">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="required" xsi:type="boolean">false</item>
                <item name="validation" xsi:type="array">
                    <item name="required-entry" xsi:type="boolean">false</item>
                </item>
                <item name="sortOrder" xsi:type="number">40</item>
                <item name="dataType" xsi:type="string">string</item>
                <item name="formElement" xsi:type="string">textarea</item>
                <item name="label" translate="true" xsi:type="string">Author Biography</item>
            </item>
        </argument>
    </field>
    <field name="author_profile_image">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="dataType" xsi:type="string">string</item>
                <item name="source" xsi:type="string">category</item>
                <item name="label" xsi:type="string" translate="true">Author Image</item>
                <item name="visible" xsi:type="boolean">true</item>
                <item name="formElement" xsi:type="string">fileUploader</item>
                <item name="elementTmpl" xsi:type="string">ui/form/element/uploader/uploader</item>
                <item name="previewTmpl" xsi:type="string">Magento_Catalog/image-preview</item>
                <item name="required" xsi:type="boolean">false</item>
                <item name="sortOrder" xsi:type="number">50</item>
                <item name="uploaderConfig" xsi:type="array">
                    <item name="url" xsi:type="url" path="Vendor_CategoryAuthorProfile/category_thumbnail/upload"/>
                </item>
            </item>
        </argument>
    </field>
</fieldset>
</fieldset>
</form>

/app/code/Vendor/CategoryAuthorProfile/Setup/InstallData.php

<?php
namespace VendorCategoryAuthorProfileSetup;

use MagentoFrameworkModuleSetupMigration;
use MagentoFrameworkSetupInstallDataInterface;
use MagentoFrameworkSetupModuleContextInterface;
use MagentoFrameworkSetupModuleDataSetupInterface;
use MagentoCatalogSetupCategorySetupFactory;

class InstallData implements InstallDataInterface
{
public function __construct(CategorySetupFactory $categorySetupFactory)
{
    $this->categorySetupFactory = $categorySetupFactory;
}
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
{
    $installer = $setup;
    $installer->startSetup();

    $categorySetup = $this->categorySetupFactory->create(['setup' => $setup]);
    $entityTypeId = $categorySetup->getEntityTypeId(MagentoCatalogModelCategory::ENTITY);
    $attributeSetId = $categorySetup->getDefaultAttributeSetId($entityTypeId);
    $categorySetup->addAttribute(
        MagentoCatalogModelCategory::ENTITY, 'is_profile_displayed', [
            'type' => 'int',
            'label' => 'Do you want to display the author profile?',
            'input' => 'select',
            'sort_order' => 1,
            'source' => 'MagentoEavModelEntityAttributeSourceBoolean',
            'global' => MagentoEavModelEntityAttributeScopedAttributeInterface::SCOPE_GLOBAL,
            'visible' => true,
            'required' => false,
            'user_defined' => true,
            'default' => '0',
            'group' => 'Author Profile',
            'backend' => ''
        ]
    );
    $categorySetup->addAttribute(MagentoCatalogModelCategory::ENTITY, 'author_profile_name', [
        'type'     => 'varchar',
        'label'    => 'Author Name',
        'input'    => 'text',
        'required' => false,
        'sort_order' => 2,
        'visible'  => true,
        'user_defined' => true,
        'global'   => MagentoEavModelEntityAttributeScopedAttributeInterface::SCOPE_STORE,
        'used_in_product_listing' => true,
        'visible_on_front' => true,
        'group' => 'Author Profile',
    ]);
    $categorySetup->addAttribute(MagentoCatalogModelCategory::ENTITY, 'author_profile_title', [
        'type'     => 'varchar',
        'label'    => 'Author Title',
        'input'    => 'text',
        'required' => false,
        'sort_order' => 3,
        'visible'  => true,
        'user_defined' => true,
        'global'   => MagentoEavModelEntityAttributeScopedAttributeInterface::SCOPE_STORE,
        'used_in_product_listing' => true,
        'visible_on_front' => true,
        'group' => 'Author Profile',
    ]);
    $categorySetup->addAttribute(MagentoCatalogModelCategory::ENTITY, 'author_profile_bio', [
        'type'     => 'varchar',
        'label'    => 'Author Bio',
        'input'    => 'textarea',
        'required' => false,
        'sort_order' => 4,
        'visible'  => true,
        'user_defined' => true,
        'global'   => MagentoEavModelEntityAttributeScopedAttributeInterface::SCOPE_STORE,
        'used_in_product_listing' => true,
        'visible_on_front' => true,
        'group' => 'Author Profile',
    ]);
    $categorySetup->removeAttribute(MagentoCatalogModelCategory::ENTITY, 'author_profile_image' );
    $categorySetup->addAttribute(
        MagentoCatalogModelCategory::ENTITY, 'author_profile_image', [
            'type' => 'varchar',
            'label' => 'Author Image',
            'input' => 'image',
            'backend' => 'MagentoCatalogModelCategoryAttributeBackendImage',
            'required' => false,
            'sort_order' => 5,
            'global' => MagentoEavModelEntityAttributeScopedAttributeInterface::SCOPE_STORE,
            'group' => 'Author Profile',
        ]
    );
    $installer->endSetup();
}
}