Forums › Forums › OroPlatform › How to override parts of oro
This topic contains 14 replies, has 8 voices, and was last updated by kiatsiong.ng 5 years, 1 month ago.
Starting from March 1, 2020 the forum has been switched to the read-only mode. Please head to StackOverflow for support.
- CreatorTopic
- June 21, 2016 at 4:53 am #36967
Hi,
Today i want to explain how to override parts of oro.
- First of all create Custom (for example) namespace directory – src/Custom.
- Create directory for bundle which you want to override – src/Custom/Bundle/FilterBundle
- Create src/Custom/Bundle/FilterBundle/CustomFilterBundle.php which contains getParent() function. Our new bundle will know who its parent:
PHP12345678910111213<?phpnamespace Custom\Bundle\FilterBundle;use Symfony\Component\HttpKernel\Bundle\Bundle;class CustomFilterBundle extends Bundle{public function getParent(){return 'OroFilterBundle';}}- Register your bundle by creating Resources/config/oro/bundles.yml in your custom bundle with following content (this example i got from UIBundle, please change to right path)
YAML12bundles:- { name: Oro\Bundle\UIBundle\OroUIBundle, priority: 0 }Now we have new bundle ready to override parent’s bundle.
- CreatorTopic
- AuthorReplies
- June 21, 2016 at 5:04 am #36968
To override controller, create bundle similar to CustomFilterBundle and extent it from OroDashboardBundle.
- Create src/Custom/Bundle/DashboardBundle/Controller/DashboardController.php controller and override index action.
PHP1234567891011121314151617181920212223242526272829303132333435363738<?phpnamespace Custom\Bundle\DashboardBundle\Controller;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;use Oro\Bundle\SecurityBundle\Annotation\Acl;use Oro\Bundle\DashboardBundle\Controller\DashboardController as OroDashboardController;/*** @Route("/dashboard")*/class DashboardController extends OroDashboardController{/*** @Route(* ".{_format}",* name="oro_dashboard_index",* requirements={"_format"="html|json"},* defaults={"_format" = "html"}* )** @Acl(* id="oro_dashboard_view",* type="entity",* class="OroDashboardBundle:Dashboard",* permission="VIEW"* )* @Template*/public function indexAction(){return ['entity_class' => $this->container->getParameter('oro_dashboard.dashboard_entity.class')];}}- Don’t forget create file src/Custom/Bundle/DashboardBundle/Resources/config/oro/routing.yml and override oro_dashboard alias with new controller location
YAML1234oro_dashboard:resource: "@CustomFilterBundle/Controller"type: annotationprefix: /June 21, 2016 at 6:35 am #36969Suppose we want to override javascript file.
Create it, for example i want to override choice-tree-filter.js – src/Custom/Bundle/FilterBundle/Resources/public/js/filter/choice-tree-filter.js
JavaScript1234567891011121314151617181920212223242526272829define(function(require) {'use strict';var CustomChoiceTreeFilter;var _ = require('underscore');var __ = require('orotranslation/js/translator');var ChoiceTreeFilter = require('oro/filter/choice-tree-filter');var tools = require('oroui/js/tools');CustomChoiceTreeFilter = ChoiceTreeFilter.extend({emptyValue: {type: 1,value: __('All')},initialize: function() {CustomChoiceTreeFilter.__super__.initialize.apply(this, arguments);},/*** @inheritDoc*/_getCriteriaHint: function() {//put your code}});return CustomChoiceTreeFilter;});and register it in src/Custom/Bundle/FilterBundle/Resources/config/requirejs.yml
YAML12345678910config:map:'*':'oro/filter/choice-tree-filter': 'customfilter/js/filter/choice-tree-filter''customfilter/js/filter/choice-tree-filter':'oro/filter/choice-tree-filter': 'oro/filter/choice-tree-filter'config:paths:'customfilter/js/filter/choice-tree-filter': 'bundles/customfilter/js/filter/choice-tree-filter.js'June 22, 2016 at 1:22 am #36970Please run these commands after javascript changes
Shell123app/console oro:assets:install --env=dev --symlinkapp/console assetic:dump --env=devapp/console oro:requirejs:build --env=devand this command after yml modifications
Shell1app/console cache:clearOctober 3, 2016 at 5:47 am #36971Today we are talking about service overriding. To override service you must create own bundle, after that there is two ways. The example override Oro\Bundle\ImportExportBundle\Reader\EntityReader service.
First:
Create your custom entity reader
PHP1234567891011121314151617181920212223242526272829<?phpnamespace Custom\Bundle\OroBundle\Reader;use Oro\Bundle\ImportExportBundle\Reader\EntityReader as BaseEntityReader;use Oro\Bundle\ImportExportBundle\Context\ContextInterface;use Oro\Bundle\ImportExportBundle\Exception\InvalidConfigurationException;class EntityReader extends BaseEntityReader{/*** @param ContextInterface $context* @throws InvalidConfigurationException*/protected function initializeFromContext(ContextInterface $context){if ($context->hasOption('entityName')) {$this->setSourceEntityName($context->getOption('entityName'), $context->getOption('organization'));} elseif ($context->hasOption('queryBuilder')) {$this->setSourceQueryBuilder($context->getOption('queryBuilder'));} elseif ($context->hasOption('query')) {$this->setSourceQuery($context->getOption('query'));} elseif (!$this->getSourceIterator()) {throw new InvalidConfigurationException('Configuration of entity reader must contain either "entityName", "queryBuilder" or "query".');}}}Add to src/Custom/Bundle/OroBundle/Resources/config/reader.yml these lines (‘oro_importexport.reader.entity.class’ parameter must be the same that in original class, change only path to class):
YAML12parameters:oro_importexport.reader.entity.class: Custom\Bundle\OroBundle\Reader\EntityReaderand register reader.yml in src/Custom/Bundle/OroBundle/DependencyInjection/CustomOroExtension.php
PHP1234567891011121314151617181920<?phpnamespace Custom\Bundle\OroBundle\DependencyInjection;use Symfony\Component\HttpKernel\DependencyInjection\Extension;use Symfony\Component\DependencyInjection\ContainerBuilder;use Symfony\Component\Config\FileLocator;use Symfony\Component\DependencyInjection\Loader;class CustomOroExtension extends Extension{/*** @inheritDoc*/public function load(array $configs, ContainerBuilder $container){$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));$loader->load('reader.yml');}}Second (via compiler pass):
PHP123456789101112131415<?phpnamespace Custom\Bundle\OroBundle\DependencyInjection\CompilerPass;use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;use Symfony\Component\DependencyInjection\ContainerBuilder;class OverrideCompilerPass implements CompilerPassInterface{public function process(ContainerBuilder $container){$definition = $container->getDefinition('original_service_definition');$definition->setClass('full path to override class name');}}and register it in CustomOroBundle.php
PHP1234567891011121314151617<?phpnamespace Custom\Bundle\OroBundle;use Symfony\Component\HttpKernel\Bundle\Bundle;use Custom\Bundle\OroBundle\DependencyInjection\CompilerPass\OverrideCompilerPass;class CustomOroBundle extends Bundle{public function build(ContainerBuilder $container){parent::build($container);$container->addCompilerPass(new OverrideCompilerPass());}}June 26, 2017 at 7:28 am #36972Hi Mike,
I want to override the execute methode of the console command “oro:magento:initial:sync”.
I have create bundle inherit from MagentoBundle and override InitialSyncCommand but the parent command is still executed but not mine. My bundle is loaded after the OroMagentoBundle.
How can I solve the problem ?PHP123456789101112131415161718192021222324<?phpnamespace Sinabs\Bundle\ExtendMagentoBundle\Command;use OroCRM\Bundle\MagentoBundle\Command\InitialSyncCommand as OroInitialSyncCommand;use Symfony\Component\Console\Input\InputInterface;use Symfony\Component\Console\Output\OutputInterface;class InitialSyncCommand extends OroInitialSyncCommand {const COMMAND_NAME = 'oro:magento:initial:sync';public function configure() {$this->setName(self::COMMAND_NAME)->setDescription('Run initial synchronization for magento channel.');}public function execute(InputInterface $input, OutputInterface $output) {$output->writeln("skipped");return;}}July 18, 2017 at 3:45 am #36973How did you declare the bundle in bundles.yml?
March 15, 2018 at 3:11 am #36974Considering your documentation on https://oroinc.com/orocrm/forums/topic/how-to-override-parts-of-oro/#post-63331
Is it possible to have 2 bundles extending the same js component? Imagine you have bundle A that adds component A and bundle B that adds component B. And you want, on both bundles, initialize the component on line-item-view.js (order contexts, like you do for product-unit-component)
If we extend LineItemView adding on initialize method the init of new components, in both bundles, then just the one with high priority will be executed, right?
what would be the best (and clean) approach for these case?
ThanksMarch 15, 2018 at 8:22 am #36975Hello nevoeiro,
Not sure that, I understood completely your case. But will try to help.
Here’s article in Oro Book related to your question:
https://oroinc.com/orocrm/doc/2.3/book/javascript-modularity#map
See how to configure RequireJS to use another version of module.But it won’t work if two bundles provide their own extend for same original module. E.g.
YAML123456config:map:'*':'jquery': 'mybundle/js/jquery-extend''mybundle/js/jquery-extend':'jquery': 'jquery'Only one extend will be loaded when you call
require('jquery')
To solve that issue, you need to do following:
- the bundle with second extend has to have higher priority over bundle with first extendYAML12bundles:- { name: My\Bundle, priority: 50 }
- second extend has to override map for original map. Example:YAML1234config:map:'*':'jquery': 'mybundle/js/extend/jquery'
- module with second extend has to require first extend123456789define(function(require) {'use strict';var $ = require('oroui/js/extend/jquery');// add your extendreturn $;});
If it did not help, please explain your case in more detailed examples.
March 21, 2018 at 5:29 am #36976Hi Mike,
I’m trying to replace a service using the first option you’ve suggested. It looks simple but somehow I cannot get it work. This is the service I’m trying to replace:
PHP1oro_web_catalog.layout.data_provider.menu_dataSo, I created a “parameters.yml” file on “MyVendor\Bundle\MyBundle\Resources\config” with the following definition:
PHP12parameters:oro_web_catalog.layout.data_provider.menu_data.class: MyVendor\Bundle\MyBundle\Layout\DataProvider\MenuDataProviderThen, registered it with:
PHP12345public function load(array $configs, ContainerBuilder $container) : void{$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));$loader->load('parameters.yml');}Unfortunately it always use the original service and ignores mine.
Any hint?Thanks in advance.
March 21, 2018 at 6:06 am #36978Hi, daniel.coelho.
this is definition of service that you try to override: https://github.com/oroinc/orocommerce/blob/master/src/Oro/Bundle/WebCatalogBundle/Resources/config/services.yml#L264-L273
There are no parameter with name “oro_web_catalog.layout.data_provider.menu_data.class“.
So, in that case you can use, for example, service decoration approach. See https://symfony.com/doc/current/service_container/service_decoration.html.
To comply with backward compatibility I recommend you to extend original class “Oro\Bundle\WebCatalogBundle\Layout\DataProvider\MenuDataProvider” in your custom class.
March 21, 2018 at 6:24 am #36980Hi msulima,
Thanks for your answer.
Initially I thought about the decoration approach but the think is that I want to add logic on “prepareItemsData” method. That’s why tried to replace the service.March 21, 2018 at 6:30 am #36981Ok, lets extend from original service. You can call parent methods or not in your customization.
March 19, 2019 at 7:54 pm #38385I am a total noob on Symfony and Oro Platform. I want to increase the length of name for MySQL table from 30 to 64 as I encountered this error:
Shell123456[kiat@reporting misoro]$ sudo -u nginx php bin/console oro:migration:load --forceProcess migrations...> Oro\Bundle\EntityExtendBundle\Migration\LoadEntityConfigStateMigration> Stars\Bundle\LoggerEventBundle\Migraions\Schema\v1_0\StarsLoggerEventBundleERROR: Max table name length is 30. Please correct "sc_stars_logger_event_action_data" tablein "Stars\Bundle\LoggerEventBundle\Migraions\Schema\v1_0\StarsLoggerEventBundle" migrationThe code that returns length 30 is from:
PHP123456789101112131415<?phpnamespace Oro\Bundle\MigrationBundle\Tools;class DbIdentifierNameGenerator{/*** Gets the max size of an identifier** @return int*/public function getMaxIdentifierSize(){return 30;}I can override the parameters as it is defined in the services.yml:
YAML12parameters:oro_migration.db_id_name_generator.class: Stars\Bundle\MigrationBundle\Tools\DbIdentifierNameGeneratorHowever, that doesn’t work because of this:
Shell123[kiat@reporting misoro]$ sudo -unginx php bin/console debug:container --parameters | grep DbIdentifieroro_migration.db_id_name_generator.classOro\Bundle\EntityExtendBundle\Tools\ExtendDbIdentifierNameGeneratorI traced the overriding to this code:
PHP123456789101112131415161718192021222324252627<?phpnamespace Oro\Bundle\EntityExtendBundle\DependencyInjection\Compiler;use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;use Symfony\Component\DependencyInjection\ContainerBuilder;use Symfony\Component\DependencyInjection\Reference;class MigrationConfigPass implements CompilerPassInterface{// ...const MIGRATIONS_NAME_GENERATOR_CLASS_PARAM = 'oro_migration.db_id_name_generator.class';/*** {@inheritdoc}*/public function process(ContainerBuilder $container){if ($container->hasParameter(self::MIGRATIONS_NAME_GENERATOR_CLASS_PARAM)) {$container->setParameter(self::MIGRATIONS_NAME_GENERATOR_CLASS_PARAM,'Oro\Bundle\EntityExtendBundle\Tools\ExtendDbIdentifierNameGenerator');}// ...}}Given the above, how should I approach overriding the function generateIndexName()? I would appreciate any guidelines that anyone can advise.
- This reply was modified 5 years, 1 month ago by
kiatsiong.ng.
March 20, 2019 at 3:08 am #38388I managed to override the service with compiler pass.
- AuthorReplies
The forum ‘OroPlatform’ is closed to new topics and replies.