0
system.xml file
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
 <system>
 <section id="specials_subcategory" translate="label" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1">
 <class>separator-top</class>
 <label>Category Specials</label>
 <tab>ThreeYearOrders</tab>
 <resource>Gelmar_SpecialsSubCategory::config</resource>
 <group id="general" translate="label" type="text" sortOrder="110" showInDefault="1" showInWebsite="1" showInStore="1">
 <label>Settings</label>
 <field id="run_specials_logic" translate="label" type="button" sortOrder="2" showInDefault="1" showInWebsite="0" showInStore="0">
 <label>Update Category Specials</label>
 <button class="action specials" type="button">
 <span>Update</span>
 </button>
 <action>
 <url path="gelmar/specials/run" />
 </action>
 </field>
 </group>
 </section>
 </system>
</config>

This is my system.xml file. The settings label and button both display but the button has no text. I simply just want the button to say "Update". Please advise or give suggestions. Next I need help with my functionality. Below I have my Run.php file which is supposed to add the corresponding category ID to the product if it is in the specials category. So for example if I have a product that is in my Bathroom category and is on special it should add to the Bathroom specials category. I have double checked the IDs and they are all correct however it does not seem to be working.

Run.php file
<?php
namespace Gelmar\SpecialsSubCategory\Controller\Adminhtml\Specials;
use Magento\Backend\App\Action;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
use Magento\Catalog\Api\CategoryLinkManagementInterface;
use Magento\Framework\Controller\ResultFactory;
class Run extends Action
{
 protected $productCollectionFactory;
 protected $categoryLinkManagement;
 public function __construct(
 Action\Context $context,
 ProductCollectionFactory $productCollectionFactory,
 CategoryLinkManagementInterface $categoryLinkManagement
 ) {
 parent::__construct($context);
 $this->productCollectionFactory = $productCollectionFactory;
 $this->categoryLinkManagement = $categoryLinkManagement;
 }
 public function execute()
 {
 // Category IDs
 $specialsCategoryId = 206;
 $mapping = [
 249 => 259,
 5 => 260,
 21 => 261,
 19 => 262,
 24 => 263,
 28 => 264,
 53 => 265
 ];
 // Get all products in the Specials category (206)
 $productCollection = $this->productCollectionFactory->create()
 ->addCategoriesFilter(['in' => $specialsCategoryId]);
 // Consider adding pagination or limiting the collection size
 // $productCollection->setPageSize(100)->setCurPage(1);
 // Loop through the products
 foreach ($productCollection as $product) {
 $categoryIds = $product->getCategoryIds();
 // Use array_intersect() for better performance
 $categoriesToAdd = array_intersect(array_keys($mapping), $categoryIds);
 $newCategoryIds = array_merge($categoryIds, array_map(function($id) use ($mapping) {
 return $mapping[$id];
 }, $categoriesToAdd));
 // Ensure no duplicates
 $newCategoryIds = array_unique($newCategoryIds);
 // Only update if categories have changed
 if ($newCategoryIds !== $categoryIds) {
 try {
 $this->categoryLinkManagement->assignProductToCategories($product->getSku(), $newCategoryIds);
 } catch (\Exception $e) {
 // Log the error or handle it as needed
 $this->messageManager->addErrorMessage(__('Error assigning categories to product %1: %2', $product->getSku(), $e->getMessage()));
 }
 }
 }
 // Display success message in the admin
 $this->messageManager->addSuccessMessage(__('Specials category update completed successfully.'));
 // Redirect back to the config page
 $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
 $resultRedirect->setPath('adminhtml/system_config/edit/section/specials_subcategory');
 return $resultRedirect;
 }
}

I am not sure if my Run.php file is incorrect or if my system.xml file is incorrect. Basically what I want to happen is to be able to click a button on the admin side and then it updates the products that are on special to add the necessary category IDs such as Bathroom specials and then has a message to say all products have been updated. Please advise and give suggestions

asked Oct 21, 2024 at 13:58

2 Answers 2

1

for button and controller to work, try below reference code and amend changes accordingly

<field id="sent" translate="label" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
 <label></label>
 <button_label>Test Now</button_label>
 <button_url>adminhtml/smtp/test</button_url>
 <frontend_model>Mageplaza\Smtp\Block\Adminhtml\System\Config\Button</frontend_model>
</field>

 <?php
/**
 * Mageplaza
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Mageplaza.com license that is
 * available through the world-wide-web at this URL:
 * https://www.mageplaza.com/LICENSE.txt
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade this extension to newer
 * version in the future.
 *
 * @category Mageplaza
 * @package Mageplaza_Smtp
 * @copyright Copyright (c) Mageplaza (https://www.mageplaza.com/)
 * @license https://www.mageplaza.com/LICENSE.txt
 */
namespace Mageplaza\Smtp\Block\Adminhtml\System\Config;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;
/**
 * Class Button
 * @package Magento\Paypal\Block\Adminhtml\System\Config
 */
class Button extends Field
{
 /**
 * @var string
 */
 protected $_template = 'system/config/button.phtml';
 /**
 * Unset scope
 *
 * @param AbstractElement $element
 *
 * @return string
 */
 public function render(AbstractElement $element)
 {
 $element->unsScope();
 return parent::render($element);
 }
 /**
 * Get the button and scripts contents
 *
 * @param AbstractElement $element
 *
 * @return string
 */
 protected function _getElementHtml(AbstractElement $element)
 {
 $originalData = $element->getOriginalData();
 $this->addData([
 'button_label' => $originalData['button_label'],
 'button_url' => $this->getUrl($originalData['button_url'], ['_current' => true]),
 'html_id' => $element->getHtmlId(),
 ]);
 return $this->_toHtml();
 }
}
answered Oct 22, 2024 at 8:36
1
  • Thanks for your response but please could you give more detail, as I am slightly confused. Im assuming I will replace my field id="run_specials_logic" field with the first code snippet you provided. Then what do I do with the second code snippet you provided? Do I add this to my controller or create a new file? Commented Oct 22, 2024 at 9:10
0

Yours will be

<field id="run_specials_logic" translate="label" type="button" sortOrder="2" showInDefault="1" showInWebsite="0" showInStore="0">
 <label></label>
 <button_label>Update</button_label>
 <button_url>gelmar/specials/run</button_url>
 <frontend_model>Gelmar\SpecialsSubCategory\Block\Adminhtml\System\Config\Button</frontend_model>
 </field>

That will be new file Gelmar\SpecialsSubCategory\Block\Adminhtml\System\Config\Button

answered Oct 22, 2024 at 10:14
2
  • Ok thank again for your help. So I will edit my system.xml file to have that code snippet. Then I will create the new file in that directory but what must the file name be and will it be .PHP? So must I create the file and name it Button.php? Commented Oct 22, 2024 at 10:43
  • Yeah Button.php will be the file name Commented Oct 22, 2024 at 11:04

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.