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
2 Answers 2
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();
}
}
-
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?Rorke– Rorke2024年10月22日 09:10:52 +00:00Commented Oct 22, 2024 at 9:10
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
-
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?Rorke– Rorke2024年10月22日 10:43:39 +00:00Commented Oct 22, 2024 at 10:43
-
Yeah Button.php will be the file nameKareem k– Kareem k2024年10月22日 11:04:25 +00:00Commented Oct 22, 2024 at 11:04