Registering new custom ComputedItem to ComputedItemTypesRegistry - intershop

By following the Cookbook - Basket Calculation (https://support.intershop.com/kb/index.php/Display/23V395)
I have created two new custom computed items with unique jaxb name:
Also both of this computed items are registered in ComputedItemTypeRegistry in custom class which extends Cartridge class:
And now when the calculation is called and new calculation rule is executed i am getting an exception that first computed item MKComputedBenefitItemImpl is not registered:

New cartridge class A1MKCartridge wasn't recognized due to wrong location of cartridge properties.
Guide - 7.10 Migration of Cartridge Properties:
https://support.intershop.com/kb/index.php/Display/28Z691
The <cartridge_name>.properties were moved from \share\system\config\cartridges to <cartridge_name>\src\main\resources\cartridges in ICM 7.10. This has the following implications.

Related

Override SyliusCoreBundle Model User

Question pretty much duplicates How to override SyliusCoreBundle Model User
but answers in original question doesn't seem to cover it.
So the question is:
what are the minimum steps to override this model adding a new field?
I created new bundle, added a model to an Entity folder and added the following
to app/config.yml:
sylius_resource:
resources:
sylius.user:
classes:
model: myVendor\myBundles\webBundle\Entity\User
but still project uses Sylius\Component\Core\Model\User model.
can I use annotations defining my model?
You were almost there, and yes the below steps are not in the book yet - not sure why.
Apart from the above you need to change the mapping in sylius.yml which is present in /vendor/sylius/sylius/src/Sylius/Bundle/CoreBundle/Resources/config/app/sylius.yml
Change in two places
sylius_installer:
classes:
user:
# model: Sylius\Component\Core\Model\User # comment this out
model: Acme\YourBundle\Entity\User
sylius_resource:
resources:
sylius.user:
driver: doctrine/orm
classes:
# model: Sylius\Component\Core\Model\User # comment this out
model: Acme\YourBundle\Entity\User
For your first question :
You need to create a new entity class which extends the original User Model and place it in the above snippet put the path to your new entity class.
In the Entity class you need to define your new fields and then their setters and getters. Also, you need to define an interface as well with the same name as the entity class like : UserInterface.php, just put in the method declarations of your extended entity class and have your entity implement this interface.
Also you need to create an doctrine mapping file in Acme/YourBundle/Resources/config/doctrine/User.orm.xml. You can do through the documentation present at sylius user documentation to see the steps.
Final step is to add the mapping which you have already done in app/config/config.yml.
For your Second question :
You can use annotations in the sources you define in your own bundle i.e Acme/YourBundle but within the sylius sub bundles like resourcebundle etc you need to use what is being used within it already.
If there is a better way to doing this - please let me know as well !

Automatic Localization in symfony2

Please look at the following code:
public function __construct($error_code)
{
$translator = new Translator('en');
$translator->addLoader('yaml', new YamlFileLoader());
$translator->addResource('yaml', dirname(__DIR__).'/Resources/translations/messages.en.yml', 'en');
$this->setErrorCode($translator->trans($error_code));
}
I am new to symfony. I have created a class MyProjectExceptions which extends Exception. Now when I have to throw a custom exception I call this class where I get the $error_code. Now this $error_code is a constant of another class which has its locale in MyBundle/Resources/transalations/messages.en.yml which will be used to throw as exception message.
Now my question are following:
How can I avoid addResource, so it can automatically add it based on Locale and find the string?
How to access serviceContainer in this class so that I can access session to set and get locales OR other services.
Can we set the default Loader as well.
In above code I am creating an instance of Translator class and manually passing 'en'. but it should pick default locale or user set locale.
I tried many solutions but not able to get the desired results.
Any help would be appreciated. Thanks in advance.
You need to register your class as Symfony service. Read the documentation: http://symfony.com/doc/current/book/service_container.html#creating-configuring-services-in-the-container
After that you can inject other services (like Translation) in your constructor. It will use all parameters that you have already set.
If you inject translator service it will pick the parameters that you have already set. For example, if you defined parameters for translator (including default locale) at config.yml, then you overrode this locale with parameter in route, you will get translator service set up with this locale. And it will automatically use resources that are lied in appropriate directories.

symfony dynamically add translation based on condition

I'm searching for a way to add a translation to an existing translation catalogue during runtime.
I have a working symfony 2.3 application which uses translations in de/en/fr/it and fetches all available translation keys from /Resources/translations/messages..yml.
Now if a user logs in I want to have the possibility to override some of the already loaded labels based on setting for that user (e.g. textfield in DB which holds key-value-pairs).
E.g.
messages.en.yml
company.name.short: Company profile
Usersetting:
company.name.short: Profile for company
I found no way to add/override keys to the existing catalogue or to make them available in twig. Is there a Bundle or a setting or some Symfony magic to get this to work?
You'll probably want to extend Symfony's own translation class for this. This article explains how to do that:
http://www.webtipblog.com/extend-symfony-2-translator-to-log-untranslated-messages-to-a-database/
The key point is to override the "translator.class" parameter in your config, and then point it to your own class that first checks for database overrules and will defer to the symfony default implementation if it cannot find one.

Does Symfony2 Dependency Injection support Object Lifestyle?

I have a class which I load via dependency injection within Symfony 2.
It has a number of default private variables which I can override with setters.
Problem is, once one of those default values are set to something else within a page, there is no way to set it back automatically.
I don't want to call the class again using new as it removes the usefulness of the dependency injection.
So, does Symfony2 support Object LifeStyle, or do I basically need to write a public function which resets all of the defaults back to normal and call it each time it is required.
As an example, I use a class to get remote files. It has defaults for UserAgent, Accepted Language/Encoding, Method etc. But if I set the Method to POST, instead of the default GET for one call in a page, the next time I call it, it is still POST, where as I wish it to be the default GET once more, which it would be if I used new instead of via dependency injection.
Add scope: prototype to your service definition. This will ensure you get a new instance from the container each time you request your class. And of course the instance will have the default values.
http://symfony.com/doc/current/cookbook/service_container/scopes.html

add custom logic to internal Symfony classes like SwitchUserListener or TemplateGuesser

I got a problem to add custom logic to some Symfony classes.
SwitchUserListener
I want to add a check, that a user cannot switch to a another user, which have more rights/roles, than the initial user.
First attempt
Overwrite the parameter in the security_listeners.xml with the key:
security.authentication.switchuser_listener.class But where can I overwrite it?
In the security.yml it didn't work:
security:
...
authentication:
switchuser_listener:
class: Symfony\Component\Security\Http\Firewall\SwitchUserListener
Second attempt
Overwrite the service for the SwitchUserListner service id: security.authentication.switchuser_listener
I create the same service in my service.xml of my bundle, but my class was not used / called.
Another idea was to overwrite only the class, but that only works for bundles, but the SwitchUserListener was not in the SecurityBundle, it was in the symfony component directory and that seemed to me as a really bad idea to overwrite the SecurityBundle
Third attempt
Now I get the solution: First time I didn't realize that the dispatcher call listener for the SWTICH_USER event in the SwitchUserListener:
$switchEvent = new SwitchUserEvent($request, $token->getUser());
$this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent);
So I need only to create a service with the special tag for this event type:
<tag name="kernel.event_listener" event="security.switch_user" method="onSecuritySwitchUser" />
And do the check in the given method.
This seems to be a better solution thatn the other two. But there is still a problem. In my listener for the SwitchUserEvent I need to ignore my custom check if the user wants to exit the switched user.
So I need to check the requested path: ignore if path containts '?switch_user=_exit'
But the path (URL parameter) can be changed:
# app/config/security.yml
security:
firewalls:
main:
# ...
switch_user: { role: ROLE_ADMIN, parameter: _want_to_be_this_user }
But in my bundle I can't read this parameter, because it will not be passed to the service container. It will be passed to the constructor of the SwitchUserListner class and will be saved there as private attribute, never accessable (without Reflection) from outside. (that happens here: SecurityExtension.php line 591) So what to do? Define the parameter twice go against DRY. Use Reflection?
And the other point is that there aren' every time events that will be fired on which I write a subscriber class. So what would be another / best solution for it?
I ask this question because I will get some similar problem where I want to add or overwrite something of the symfony intern components.
TemplateGuesser
I wanted to modify the TemplateGuesser: For a specific bundle all Templates which has the annotation #Tempalte the tempate file should be located with the controller TestController#showAction at this path:
Resources/views/customDir/Test/show.html.twig
So the guesser should be put and locate everything into a additional folder customDir instead of using only views. When using the render function with a specific template, the guesser should ignore the annotation.
I created my own Guesser and overwrite the service id: sensio_framework_extra.view.guesser and in comparision to the SwitchUserListener this time my class is really called instead of the original guesser. Why it works here but not with the SwitchUserListener?
Is this a good solution at all? I also tried to add a second listener, which calls the TemplateGuesser, its the service sensio_framework_extra.view.listener with the class Sensio\Bundle\FrameworkExtraBundle\EventListener\TemplateListener But that didn't work.
Whenever you need to add custom logic or extend the framework behaviour, you can use and abuse the container configuration. That means you can overwrite pretty much every service Symfony defines by just creating a new class that extends that service – or not, really – and creating the service definition for it with the same key as the original service you wanted to extend or change behaviour.
For instance, Symfony has a base template guesser registered as a service with the sensio_framework_extra.view.guesser id. If you want to extend that or change behaviour, you only need to create your own class and register it with the same id of the original service – remember that the bundles loading order affects the service definitons with the same id, where the last one loaded is the one that will be created.
That should solve both of your problems.

Resources