I am working on Magento 2 platform.
I have created my custom modue name MerchantTrack.
Into events.xml (MagentoSite\app\code\Magento\MerchantTrack\Checkout\etc\frontend\events.xml) written code
below
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="checkout_onepage_controller_success_action ">
<observer name="merchanttrack_checkout_onepage_controller_success_action" instance="Magento\MerchantTrack\Checkout\Observer\MyObserver" />
</event>
</config>
Into MyObserver.php(MagentoSite\app\code\Magento\MerchantTrack\Checkout\Observer\MyObserver.php) written code below
<?php
namespace Magento\MerchantTrack\Checkout\Observer;
use Magento\Framework\Event\ObserverInterface;
class MyObserver implements ObserverInterface {
public function execute(\Magento\Framework\Event\Observer $observer)
{
$orderIds = $observer->getEvent()->getOrderIds();
echo $orderId = $orderIds[0]; exit;
}
}
When placed order, into success (/MagentoSite/checkout/onepage/success/) page i can not see orderid which i echo into observer page. So I can not understand my event is fired or not.
What am I doing wrong?
You have to follow module directory structure properly.
See:
https://devdocs.magento.com/guides/v2.3/extension-dev-guide/build/module-file-structure.html#module-file-structure
MagentoSite\app\code\Magento\MerchantTrack\Checkout\etc\frontend\events.xml
You have created extra folder i.e Magento
Your directory should look like this.
MagentoSite\app\code\MerchantTrack\Checkout\etc\frontend\events.xml
Related
I tried to create a file upload field in flexform of an extbase extension in TYPO3 10. since the internal_type "file" is not supported in TYPO3 10, I tried the below given code.
<settings.bgImage>
<TCEforms>
<label>Background Image</label>
<config>
<type>inline</type>
<maxitems>1</maxitems>
<foreign_table>sys_file_reference</foreign_table>
<!--<foreign_field>uid_foreign</foreign_field>-->
<foreign_table_field>tablenames</foreign_table_field>
<foreign_label>uid_local</foreign_label>
<foreign_sortby>sorting_foreign</foreign_sortby>
<foreign_selector>uid_local</foreign_selector>
<foreign_selector_fieldTcaOverride type="array">
<config>
<appearance>
<elementBrowserType>file</elementBrowserType>
<elementBrowserAllowed>jpg,jpeg,png,svg</elementBrowserAllowed>
</appearance>
</config>
</foreign_selector_fieldTcaOverride>
<foreign_match_fields type="array">
<fieldname>image</fieldname>
</foreign_match_fields>
<appearance type="array">
<newRecordLinkAddTitle>1</newRecordLinkAddTitle>
<createNewRelationLinkTitle>Add Image</createNewRelationLinkTitle>
<headerThumbnail>
<field>uid_local</field>
<height>64</height>
<width>64</width>
</headerThumbnail>
</appearance>
</config>
</TCEforms>
</settings.bgImage>
But this is also not working correctly. please help me to fix this.
Thank you
Here is a currently working complete FlexForm with only a single FAL-Image field.
The config has changed again... :-(
FlexForm Example
<T3DataStructure>
<sheets>
<sDEF>
<ROOT>
<TCEforms>
<sheetTitle>Example 1</sheetTitle>
</TCEforms>
<type>array</type>
<el>
<!-- example of a working fal image -->
<images>
<label>FAL-Images</label>
<config>
<type>inline</type>
<foreign_table>sys_file_reference</foreign_table>
<foreign_field>uid_foreign</foreign_field>
<foreign_sortby>sorting_foreign</foreign_sortby>
<foreign_table_field>tablenames</foreign_table_field>
<foreign_match_fields>
<!-- this will be stored in sys_file_reference.fieldname -->
<fieldname>image</fieldname>
</foreign_match_fields>
<foreign_label>uid_local</foreign_label>
<foreign_selector>uid_local</foreign_selector>
<overrideChildTca>
<columns>
<uid_local>
<config>
<appearance>
<elementBrowserType>file</elementBrowserType>
<elementBrowserAllowed></elementBrowserAllowed>
</appearance>
</config>
</uid_local>
</columns>
</overrideChildTca>
<filter>
<userFunc>TYPO3\CMS\Core\Resource\Filter\FileExtensionFilter->filterInlineChildren</userFunc>
<parameters>
<allowedFileExtensions></allowedFileExtensions>
<disallowedFileExtensions></disallowedFileExtensions>
</parameters>
</filter>
<appearance>
<useSortable>1</useSortable>
<headerThumbnail>
<field>uid_local</field>
<width>45</width>
<height>45c</height>
</headerThumbnail>
<enabledControls>
<info>1</info>
<new>0</new>
<dragdrop>1</dragdrop>
<sort>0</sort>
<hide>1</hide>
<delete>1</delete>
</enabledControls>
</appearance>
</config>
</images>
<!-- end -->
</el>
</ROOT>
</sDEF>
</sheets>
</T3DataStructure>
Update: I'll show here a ViewHelper and how to use it...
Template Example
{namespace t=Your\Extension\ViewHelpers}
<f:for each="{t:FAL(uid=entry.uid, field='image', table='tt_content')}" as="preview">
<div class="preview">
<f:image src="{f:uri.image(image=preview)}" title="{preview.title}" />
<figcaption>{preview.title} {preview.description}</figcaption>
</div>
</f:for>
ViewHelper Example
<?php
namespace Your\Extension\ViewHelpers;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class FALViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
public function initializeArguments()
{
$this->registerArgument('table', 'string', '', false);
$this->registerArgument('field', 'string', '', true);
$this->registerArgument('uid', 'integer', '', true);
}
public static function renderStatic( array $arguments, \Closure $renderChildrenClosure, RenderingContextInterface $renderingContext)
{
$resFactory = \TYPO3\CMS\Core\Resource\ResourceFactory::getInstance();
$table = $arguments['table'] != NULL ? $arguments['table'] : 'tt_content';
$field = $arguments['field'];
$uid = intval($arguments['uid']);
$fileRepository = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Resource\FileRepository::class);
$fileObjects = $fileRepository->findByRelation($table, $field, $uid);
return $fileObjects;
}
}
Explanation
The images are resolved thru the table sys_file_reference.
When you take a look at it, you will find, that these fields will be filled with your extensions data:
- tablenames,
- fieldname and
- uid_foreign
A flexform field will probably have tt_content as tablenames, image as fieldname and the uid of your extensions tt_content record as uid_foreign.
The flexform defines the <fieldname>image</fieldname> ... this will become the fieldname.
The template must tell the ViewHelper what to look for: {t:FAL(uid=entry.uid, field='image', table='tt_content')}
The entry.uid must match your content element's uid.
The field='image' must match the FlexForm fieldname.
The table must match the table where the data is stored in. (Here: tt_content)
If you are using it in an extension you will need to change the tablename to your tx_yourextension_whatever.
You will probably change the fieldname as well...
Note
This code still seems to produce some deprecation warnings... I havn't yet figured out, how to overcome these :-/
Thanks for the code. I've been looking for a solution here for a while myself.
Unfortunately, the wrong image is displayed in my template.
The output in my fluid template is like this:
{f:uri.image(src:'{data.flexform_images}', treatIdAsReference:'1')}
What's wrong?
The Issue:
If your magento enterprise store has multiple currencies enabled and you are using Cart Sidebar to give a quick overview of items in the cart: Full Page Cache will be a villain when the customer try to switch between currencies. The Cart Sidebar won't get updated based on the currency switched.
I have published the answer at
http://www.eglobeits.com/blog/magento/magento-enterprise-edition-full-page-cache-mutli-currencies-mini-cart-sidebar-issue-when-switching-currencies/,
but Adding the same below for your quick reference.
The Fix:
Redefine the Cart Side Place holder container and define a new cache Id generator rather than Using fpc's original one.
Follow below Steps:
1. Create app/code/local/Egits/PageCache/etc/config.xml with following content
<?xml version="1.0"?>
<config>
<modules>
<Egits_PageCache>
<version>0.0.1</version>
</Egits_PageCache>
</modules>
</config>
2. Create app/code/etc/modules/Egits_PageCache.xml wih following content
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Egits_PageCache>
<active>true</active>
<codePool>local</codePool>
<depends>
<Enterprise_PageCache />
</depends>
</Egits_PageCache>
</modules>
</config>
3. Create app/code/local/Egits/PageCache/etc/cache.xml wih following content
<?xml version="1.0" encoding="UTF-8"?>
<config>
<placeholders>
<cart_sidebar>
<block>checkout/cart_sidebar</block>
<placeholder>CART_SIDEBAR</placeholder>
<container>Egits_PageCache_Model_Container_Sidebar_Cart</container>
<cache_lifetime>86400</cache_lifetime>
</cart_sidebar>
</placeholders>
</config>
4. Create app/code/local/Egits/PageCache/Model/Container/Sidebar/Cart.php with following content
<?php
class Egits_PageCache_Model_Container_Sidebar_Cart extends Enterprise_PageCache_Model_Container_Sidebar_Cart
{
const CURRENCY_COOKIE = 'currency';
/**
* Get cache id for the block
* #return string
*/
protected function _getCacheId()
{
$cookieCart = Enterprise_PageCache_Model_Cookie::COOKIE_CART;
$cookieCustomer = Enterprise_PageCache_Model_Cookie::COOKIE_CUSTOMER;
$curreny = array_key_exists(self::CURRENCY_COOKIE, $_COOKIE) ? $_COOKIE[self::CURRENCY_COOKIE] : '';
return md5(
Enterprise_PageCache_Model_Container_Advanced_Quote::CACHE_TAG_PREFIX
. (array_key_exists($cookieCart, $_COOKIE) ? $_COOKIE[$cookieCart] : '')
. (array_key_exists($cookieCustomer, $_COOKIE) ? $_COOKIE[$cookieCustomer] : '')
. $curreny
);
}
}
4. Flush All your caches and you are done! :).. Pretty Simple... ehhh??
Basically if a user searches for a product and the search returns emtpy, I want to be able to display a specific category under the text "No results matched your search".
I've tried different approaches to this, but it seems the results.phtml sorts every non-matching product from the search query string. It doesn't matter if the string matches a certain group of products - it will only display these products.
I'm trying to use a simple code:
<?php echo $this->getLayout()->createBlock('catalog/product_list')->setCategoryId(4)->setTemplate('catalog/product/list.phtml')->toHtml() ?>
This piece of code works anywhere on the template pages except results.phtml since the search feature blocks all non-matching products. (It will display a product if it matches the search using this code block).
Similar problem here, but no solution: Display specific category products on no results search page
Thanks, appreciate any answer to this question :-)
You can create custom block as follows and set pagination like here
<?php echo $this->getLayout()->createBlock('yourmodule/product_customlist')->setTemplate('catalog/product/list.phtml')->toHtml() ?>
UPDATE
Create Module xml file
app/etc/modules/Custom_Products.xml
as follows
<config>
<modules>
<Custom_Products>
<active>true</active>
<codePool>local</codePool>
</Custom_Products>
</modules>
</config>
Create
app/code/local/Custom/Products/etc/config.xml
file as follows
<config>
<global>
<blocks>
<customproducts>
<class>Custom_Products_Block</class>
</customproducts>
</blocks>
</global>
</config>
Create
app/code/local/Custom/Products/Block/Customlist.php
file as follows
<?php
class Custom_Products_Block_Customlist extends Mage_Core_Block_Template
{
protected function _construct()
{
parent::_construct();
// We get our collection through our model
$this->_collection = Mage::getModel('catalog/category')->load($category_id)
->getProductCollection()
->addAttributeToSelect('*') // add all attributes - optional
->addAttributeToFilter('status', 1) // enabled
->addAttributeToFilter('visibility', 4) //visibility in catalog,search
->setOrder('price', 'ASC'); //sets the order by price
// Instantiate a new Pager block
$pager = new Mage_Page_Block_Html_Pager();
// We set our limit (here an integer store in configuration).
// /!\ The limit must be set before the collection
$pager
->setLimit(5)
->setCollection($this->_collection);
// Add our Pager block to our current list block
$this->setChild('pager', $pager);
}
}
?>
Create
app/design/YOUR_PACKAGE/YOUR_THEME/template/catalog/product/customlist.phtml
as follows
<?php
$_productCollection=$this->_collection;
...
your products code here
...
?>
<?php
echo $this->getChildHtml('pager');
?>
Check if it is working for you.
I need to extend the custom success message after the customer registration. Now after registration the user is redirected to the dashboard and the standard success message is shown: "Thank you for registering with...".
I need that this message changes base on the customer group attribute. I read on-line but didn't find a working solution... but I think I'm making it in the wrong way. I started from here: http://mydons.com/simple-example-using-magento-event-observer/ to make a custom observer on the customer_register_success event, so I made the module xml named Bbox_Regmess.xml in app/etc/modules:
<config>
<modules>
<Bbox_Regmess>
<active>true</active>
<codePool>local</codePool>
</Bbox_Regmess>
</modules>
</config>
Than I made the app/code/local/Bbox/Regmess/etc and app/code/local/Bbox/Regmess/Model folders with inside the config.xml:
<config>
<modules>
<Bbox_Regmess>
<version>0.1.0</version>
</Bbox_Regmess>
</modules>
<frontend>
<events>
<customer_register_success>
<observers>
<Bbox_Regmess_Model_Observer>
<type>singleton</type>
<class>Bbox_Regmess_Model_Observer</class>
<method>Customregmess</method>
</Bbox_Regmess_Model_Observer>
</observers>
</customer_register_success>
</events>
</frontend>
</config>
And the Observer.php that is just a first try to see if I'm able to add a custom success message:
<?php
class Bbox_Regmess_Model_Observer {
public function Customregmess($observer) {
$event = $observer->getEvent(); //Fetches the current event
$customer = $event->getCustomer();
$eventmsg = "Current Event Triggered : <I>" . $event->getName() . "</I><br/> Currently Added Product : <I> " . $customer->getCustomerName()."</I>";
//Adds Custom message to shopping cart
Mage::getSingleton('customer/session')->addSuccess($eventmsg);
}
}
?>
Now if a user registers to the shop, he get the standard registration message and there is not the custom $eventmsg
What I'm making wrong? There is another way to to that? Thanks
UPDATE:
looking deeper I found out the default success message is defined in the app/code/core/Mage/Customer/controllers/AccountController.php at line 390 (just after the line 334 where there is the definition of customer_register_success event I'm trying to work with).
at line 390 there is the _welcomeCustomer function that is in charge of setting the success message, send confirmation email and set the success redirect url:
protected function _welcomeCustomer(Mage_Customer_Model_Customer $customer, $isJustConfirmed = false)
{
$this->_getSession()->addSuccess(
$this->__('Thank you for registering with %s.', Mage::app()->getStore()->getFrontendName())
);
$customer->sendNewAccountEmail(
$isJustConfirmed ? 'confirmed' : 'registered',
'',
Mage::app()->getStore()->getId()
);
$successUrl = Mage::getUrl('*/*/index', array('_secure'=>true));
if ($this->_getSession()->getBeforeAuthUrl()) {
$successUrl = $this->_getSession()->getBeforeAuthUrl(true);
}
return $successUrl;
}
Is there any chance to extend this function so I can manage multiple success message base on the customer group?
I've look for some resource about it, but I didn't find anything usefull
I think that you must place the events tag in the global tag
<config><global>...<events>...</events>...</global>...</config>
EDIT:
and the observer file extends Varien_Event_Observer, at least that worked with mine
class Bbox_Regmess_Model_Observer extends Varien_Event_Observer{}
I have a situation where the customer wants the special price to be rounded to the nearest whole number (Example: 1922.25 => 1922.00, 1256.85 => 1257.00)
This should be only for Special prices says the customer which means, if there's no special price for the product, the price should come as it is.
Note this is not only for display. This rule applies everywhere, even invoices. So is there a way to do this easily or we should only modify the core files?
EDIT
If we modify the core framework files like Product.php or Price.php, they will get overwritten with an update right? So this should be a safe way too preferably.
This is pretty easy.
Just observe catalog_product_load_after event, and overwrite special_price with a rounded value.
Create a bootstrap file for your module:
app/etc/modules/Danslo_RoundSpecialPrice.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Danslo_RoundSpecialPrice>
<active>true</active>
<codePool>local</codePool>
<depends>
<Mage_Catalog />
</depends>
</Danslo_RoundSpecialPrice>
</modules>
</config>
Specify that we want to observe the product load event:
app/code/local/Danslo/RoundSpecialPrice/etc/config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<global>
<models>
<roundspecialprice>
<class>Danslo_RoundSpecialPrice_Model</class>
</roundspecialprice>
</models>
<events>
<catalog_product_load_after>
<observers>
<round_special_price>
<class>roundspecialprice/observer</class>
<type>singleton</type>
<method>roundSpecialPrice</method>
</round_special_price>
</observers>
</catalog_product_load_after>
<catalog_product_collection_load_after>
<observers>
<round_special_price>
<class>roundspecialprice/observer</class>
<type>singleton</type>
<method>roundSpecialPriceInCollection</method>
</round_special_price>
</observers>
</catalog_product_collection_load_after>
</events>
</global>
</config>
Then just write your observer implementation:
app/code/local/Danslo/RoundSpecialPrice/Model/Observer.php:
class Danslo_RoundSpecialPrice_Model_Observer
{
public function roundSpecialPrice($observer)
{
$product = $observer->getProduct();
if ($product->getSpecialPrice()) {
$product->setSpecialPrice(round($product->getSpecialPrice()));
}
}
public function roundSpecialPriceInCollection($observer)
{
foreach ($observer->getCollection() as $product) {
if ($product->getSpecialPrice()) {
$product->setSpecialPrice(round($product->getSpecialPrice()));
}
}
}
}
In PHP:
if (special price)
price = round(price);
Which database are you using? Maybe you could do this at database level and leave application intact. For example, if you use Firebird, you can use a computed field defined like this:
alter table prices
add customer_price
computed by (
case when special_price
then round(price,0)
else price
end)