Sylius how to override the CoreBundle Checkout process - symfony

I'm working on a project and I'd like to ask for a clean/best way to override the steps in the
Sylius\Bundle\CoreBundle\Checkout\CheckoutProcessScenario
I'd like to preserve the custom mechanics of the whole process just add a custom step at the end and remove the finalize step.
$builder
->add('security', 'sylius_checkout_security')
->add('addressing', 'sylius_checkout_addressing')
->add('shipping', 'sylius_checkout_shipping')
->add('finalize', 'sylius_checkout_finalize')
->add('payment', 'sylius_checkout_payment')
->add('purchase', 'sylius_checkout_purchase')
;
What's the best form of doing so? If it's extending the bundle and overwriting it I'd like some help with that of at least some information to point me in the right direction - currently I'm not getting any results on my own.
I've read the docs on the bundle itself but it doesn't explain how to override the built in process.
I've also read the symfony cookbook on extending resources:
http://symfony.com/doc/2.0/cookbook/bundles/inheritance.html#overriding-resources-templates-routing-translations-validation-etc
and:
http://symfony.com/doc/current/cookbook/bundles/override.html
If anyone has some experience on the topic and would like to share thier insights I'd be very gratefull. Thanks in advance.

You could change the service class to a custom one.
You can overwrite the parameter sylius.checkout_scenario.class.
app/config/config.yml:
<parameter key="sylius.checkout_scenario.class">
Your\Class
</parameter>

I've done it a bit different but still the point was good :)
What I've done is use the service compiler to override it with my own class and override the original file. The basics are explained here:
http://symfony.com/doc/current/cookbook/bundles/override.html
in the Services & Configuration section :)
Then I just had to include the compiler pass
// src/Acme/ShopBundle/AcmeShopBundle.php
namespace Acme\ShopBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Acme\ShopBundle\DependencyInjection\Compiler\CustomCompilerPass;
class AcmeMailerBundle extends Bundle
{
public function build(ContainerBuilder $container)
{
parent::build($container);
$container->addCompilerPass(new CustomCompilerPass());
}
}
Inside the compiler pass I just extended the base file and overwrote the function I needed. Droppin it by in case anyone needs to pointed in the right direction.

Related

Symfony2: Best way for logging from anywhere

I am working on my first Symfony project. I wonder what is the best / recommendet method to write log messages from anywhere in my code.
So far I used Monolog which works great when being used in a controller:
public function indexAction() {
$logger = $this->get('logger');
$logger->info('I just got the logger');
$logger->error('An error occurred');
// ...
}
But how can I use this code from any classe/code from my project? Doctrine entity classes for example cannot use $this->get('logger') to create the logger. How can I access the service in these classes? Or what other methode to log message is recommended in these cases?
EDIT: Of course I could create the logger in any controller and pass it down to all other classes. But this would be quite very cumbersome. There has to be a better way.
IMO, a first approach could be the creation of Event Listeners for specific actions in order to log only what you have decided to.
Have a look to this chapter : http://symfony.com/doc/current/cookbook/event_dispatcher/event_listener.html
Hope it will help you.

Bundle /service override chain in Symfony2?

Is there a possibility to construct bundle override chains in Symfony2?
For example, there is a CoreFeatureX in the product core. And there are two plugins extending that feature PluginA and PluginB.
Using standard methods from here or from here plugins can override CoreFeatureX no problem. But only one of them at a time can currently do that.
Is there a possibility to automatically construct override chains so that if both PluginA and PluginB registered in the system, they can both extend CoreFeatureX (may be, by inheriting from each other automatically) but be unaware of each other?
Similiar extension technology is used by XenForo forum system, for example. XenForo constructs an inheritance chain from plugins, that were registered as some core class extensions. It then exposes the topmost class of the extension chain as that core class itself.
Since Symfony2 doesn't let us to extend the same bundle twice at the same time, you can't to that in "clean" Symfony2.
This is clearly implemented in Symfony\Component\HttpKernel\Kernel::initializeBundles() here:
protected function initializeBundles()
{
// (...)
foreach ($this->registerBundles() as $bundle) {
//(...)
if ($parentName = $bundle->getParent()) {
if (isset($directChildren[$parentName])) {
throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
}
//(...)
$directChildren[$parentName] = $name;
} else {
$topMostBundles[$name] = $bundle;
}
}
//(...)
}
I guess this is for a reason. Anyway you could try to override Kernel class behavior of initializeBundles method (in AppKernel class). In the line where exception above if thrown, you could change parent bundle from CoreFeatureX to the last in chain.
In case of PluginB change parent bundle to PluginA because it already extends CoreFeatureX.
In case of PluginC change parent bundle to PluginB because it is on the end of current inheritance chain.
I don't know if it could work, it's just an idea. Anyway that would be an interesting experiment. ;-)
Edit.
I just notined in your comment to the question that you wrote:
But the requirement is for both PluginA and PluginB to extend
CoreFeatureX and to be unaware of each other.
Well there's something wrong here. How do you want to override one plugin by the second and on the other side make them unaware of each other? Doesn't make sense for me.

Overriding page_list controller inside a package in Concrete5.6.1.2

Is there a way to override the controller file located at /concrete/blocks/page_list/controller.php and place it inside /packages/mypackage/blocks/page_list/? I'd like to make some changes to the original edit and view.
In /packages/mypackage/blocks/page_list/controller.php, I tried doing this but it does not seem to have any effect:
class PageListBlockController extends Concrete5_Controller_Block_PageList { ... }
You can now override/extend core classes via packages in newer versions Concrete5 (v.5.6+).
You must add to your package's main controller.php file:
public function on_start(){
$objEnv = Environment::get();
$objEnv->overrideCoreByPackage('blocks/page_list/controller.php', $this);
}
You don't have to copy over the whole core controller, just declare your new block controller like this:
class PageList extends Concrete5_Controller_Block_Page_List {
public function mymethod() {
}
}
(what class you're extending and where you put the file may vary depending on your C5 version - just compare the /concrete/ folder structure and files for reference)
The following C5 forum posts may be of help:
Overriding Core Class with Package
Can A Package Override A Core Library?
A caution, though - if you're hoping to submit to the official C5 marketplace, they generally don't accept Add-Ons with overrides.
No. You can't override a block controller from within a package. Just imagine if more than one package did this. (You can, however, have a block template within your package directory, but this makes sense because it adds rather than replaces.)
If you can, you should override by putting it in /blocks/page_list/controller.php.
However, if you still need to override it from you package, you should look into the not-very-well-supported Environment::overrideCoreByPackage() and try:
Environment::get()->overrideCoreByPackage('/blocks/page_list/controller.php', $myPackage);
See the source:
https://github.com/concrete5/concrete5/blob/master/web/concrete/core/libraries/environment.php#L123
And an example of usage:
http://www.concrete5.org/community/forums/customizing_c5/override-a-core-class-within-a-package/#460765

What is best way to add additional object classes to my symfony2 controller files?

I'm relatively new to Symfony2, so I'm learning by doing. My controller classes are getting pretty big. I'd like to break it up with functions() or objects->method(). Unfortunately I can't figure out where to put the code. (actually its really simple functions... but I can wrap that in an object...)
--I can't add it to the bottom of my DefaultController.php file. It errors out, and not pretty code to boot, either inside or outside of the { }.
--I can't simply add a new NewObject.php file to the controller directory. That errors out. The error: FatalErrorException: ...NewObject not found.
--I've toyed with manual mods to ../app/autoload.php but that doesn't really make sense for a simple class add to my ./SRC/ bundle. Perhaps I should build a ./src/autoload.php file (similiar to ./vender/autoload.php) but the contents of that file don't make sense to me at all. I simply can't figure out how the AnnotationRegistry Loader works.
Am I missing something? This seems way too hard.. what I want is a wrapped up 'include' so I can use the class in dev and after deployment.
How do I include NewObject.php (and the accompanying $newObject->function() ) in my code?
I'm told I can add a service, yet that seems like outrageous overhead for such a seemingly simple task (again, all I'm trying to do is clean up my very long controller php code...)
thanks in advance for your advice.
So you've got a project structure that looks something like this, right?
project
-- app
-- bin
-- src
-- SomeName
-- SomeBundle
-- Controller
-- Entity
-- Resources
-- ...
-- vendor
-- web
And you're just looking to have some kind of "helper" class that's used throughout your bundle. Is that correct?
If so, then you can really put it wherever you want to inside your src/ directory... Just make sure that the class name matches the file name, and that the path to the file matches the namespace you define at the top of your PHP code.
Sometimes when I do this, I'll create a simple directory under my bundle called "Helper/". Other times, when the application is more complex, I might be a little bit more explicit. But here's what the first case would look like...
First, add your /Helper directory under your bundle, and create the class file:
project
-- app
-- bin
-- src
-- SomeName
-- SomeBundle
-- Controller
-- Entity
-- Helper
-- SomeHelper.php
-- Resources
-- ...
-- vendor
-- web
The contents of SomeHelper.php might look like this:
<?php
namespace SomeName\SomeBundle\Helper;
class SomeHelper
{
public function doSomething()
{
...
}
}
Because your namespace matches the file path, it gets autoloaded, so you don't need to worry about include statements. You can instantiate that class anywhere in your bundle, as long as you include a use statement:
<?php
namespace SomeName\SomeBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use SomeName\SomeBundle\Helper\SomeHelper;
class DefaultController extends Controller
{
public function indexAction()
{
...
$helper = new SomeHelper();
$helper->doSomething();
...
}
}
Regarding the usage of services... Yes, that might be overkill, depending on what you're using it for. It's helpful to create services when the class needs to be aware of the application around it. For example, if you're creating a service that emails a User, it might want to access your database through the Doctrine service, or it might want to log the email activity through the Monolog service.
However, if your class doesn't need to know about the application (referred to as the "service container"), for example if it's just used to transfer data, then a helper class is probably more appropriate.

Using IvoryGoogleMap bundle in symfony2

I have really simple and lame question (i hope it's simple).
I'm quite new to symfony2 and i'm not sure how to use bundles. I'm trying to use IvoryGoogleMapBundle ( https://github.com/egeloen/IvoryGoogleMapBundle ) and i need to say that documentation is really good but i can't understand one thing. I'll write what have i allready done and what i need:
I've uploaded all the bundle files to src/Ivory/GoogleMapBundle directory. Added proper lines to app/autoload.php and to app/Autoload.php(according to documentation).
Now i'm trying to display the most simple map possible and there are a lot of examples in the documentation but i have no idea how to define new Map object in my controller (all the examples presuppose that $map variable allready exists and holds this object). Can you just write the most simple controller for me whitch will have this $map variable definition ? Do i need to create all those Entity files mentioned in doc ?
If something is unclear, please just tell me, i'll do my best to explain it better.
try $map = $this->get('ivory_google_map.map'); in your controller.
Full list of services you can use (under List of available services)
What are services?
Side note: external bundles should be placed in /vendor/bundles/Organization/BundleName (so /vendor/bundles/Ivory/GoogleMapBundle and not /src/Ivory/GoogleMapBundle )
or else il your controller is :
class DefaultController extends ContainerAware
{
...
}
try this:
$map = $this->container->get('ivory_google_map.map');

Resources