How to inject an interface that is part of the framework using custom class in SilverStripe - silverstripe

I am working on a SilverStripe project. Project SilverStripe version is 4.4.4. In my project, I am trying to replace a class that injected for an interface. Both the interface and the class are part of the framework.
In the framework code, it has the following class
class NaturalFileIDHelper implements FileIDHelper
As you can see, the NaturalFileIDHelper is implementing the FileIDHelper interface. What I want to do is that I want to replace all the NaturalFileIDHelper instances with my customer class called CustomFileIDHelper class that is also implementing the FileIDHelper interface.
This is what I did.
I created a custom class called, CustomFileIDHelper that is implementing the FileIDHelper interface.
Then I added the following code snippet within the mysite.yml.
SilverStripe\Assets\FilenameParsing\FileIDHelper:
class: CustomFileIDHelper
Then I rebuild the project. But my project is still using the NaturalFileIDHelper class that comes with the framework. It seems like the CustomFileIDHelper class is not used.
How can I get it working? Is it possible to do that?

I want to replace all the NaturalFileIDHelper instances with my customer class called CustomFileIDHelper class
If you want to replace all NaturalFileIDHelper instances, then that's the class you should override (not the FileIDHelper). Also the .yml config you have needs to be passed to the Injector. (https://docs.silverstripe.org/en/4/developer_guides/extending/injector/)
SilverStripe\Core\Injector\Injector:
SilverStripe\Assets\FilenameParsing\NaturalFileIDHelper:
class: CustomFileIDHelper
But this will only work if the object is instantiated through the ClassName::create() function, and I found this piece of code in the framework:
(LegacyThumbnailMigrationHelper.php)
$defaultFileIDHelper = new NaturalFileIDHelper(), // Injector is not called here.
You will need to override the classes which call new NaturalFileIDHelper() and modify it to NaturalFileIDHelper::create(), you're able to call ::create() because the NaturalFileIDHelper class have the use Injectable; trait.
Also instead of going through the troubles of overriding classes which call new NaturalFileIDHelper(), you can create a pull request to the framework repository with your NaturalFileIDHelper::create() changes instead, as it would be an improvement to the current framework code (it enables the use of dependency injection).

Related

Java FXML Application: unsuccessful calling method in controller class from external class

Working on a Java FXML application called EVIF VideoRouter. Main class is then VideoRouter.java and the controller class is called VideoRouterFXMLController.java.
I have a method in the VideoRouterFXMLController.java class that I need to be able to call from other external classes within the application. Based on extensive searching and reading, I altered the FXML loader code in the main VideoRouter.java class to be thus:
FXMLLoader EVIFloader = new FXMLLoader(this.getClass().getResource("VideoRouterFXML.fxml"));
Parent EVIFroot = (Parent) EVIFloader.load();
VideoRouterFXMLController EVIFcontroller = EVIFloader.getController();
Now, as I understand this process, I'm somehow supposed to create a getter in the main VideoRouter.java class that returns the EVIFcontroller instance I've created above? And then I can use that getter in other classes and call the method inside the returned instance?
If so, I'm having difficulty figuring out where exactly to place the getter. Does it go in the controller class, or the main class? In either case it doesn't seem to be able to see the controller instance in order to return it.
Again, I've searched extensively and the related posts I've found to not appear to address this specific problem I'm having. Any help?
Many thanks in advance!
You have already partly answered your problem: create VideoRouterFXMLController member variable in your VideoRouter class and a getter to expose it, then set it to the controller instance after you load the FXML like in the code snippet your provided.
Having said that, I would propose a different approach to your problem because this approach is generally not a good design due to high coupling between your classes. I would recommend Observer pattern as an alternative approach and EventBus as a library to do this.

Using one entity in multiple controllers

The situations' setup is like this:
1) I have two bundles in which I would like to use the same entity. So as suggested in this question and then in this article, I created the CommonEntitiesBundle where the desired Entity lives.
2) Then I described the model interface in both bundles I want to use the Entity in. So far so good.
Now I would like to use the interfaced Entity, just like I would use a 'bundle-native' one like this:
$clientData = new Client(); // the Entity class
$client->setName('Greg');
How should I approach it when there is only the interface available?
I used the interface in this controller.
In the Symfony's example there is only a use of the class via the ORM annotations.
An interface is not a class. it is instead a list of minimal necessary methods a class with 'implements [interfaceName]' must have.
Instead you could provide a example class with your bundle and use that one by default. Add configuration in app/config.yml where you can change the classname. each derived class must implement the interface for consistence.

How do I use more than one repository class in Symfony2?

I'm building an application in Symfony 2.2.
I use a custom repository class for one of my entities. I include it like this:
#ORM\Entity(repositoryClass="MyApp\MainBundle\Entity\CategoryRepository")
I want to use methods on my category entites from two other repository classes.
#ORM\Entity(repositoryClass="Gedmo\Sortable\Entity\Repository\SortableRepository")
#ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\NestedTreeRepository")
The entity, however, only expects one repositoryClass. How can I use all three of these repositories for the same entity?
I believe, you can only have one repository per Entity.
So you have referenced
ORM\Entity(repositoryClass="MyApp\MainBundle\Entity\CategoryRepository")
If you must use another repositories within the repository,
You can get the EntityManager for those Repositories (if not same) eg: $em2 = whatEverIsTheEntity()
Now you can have proxy methods in CategoryRepository to the methods in the repository you want to use. eg: $em2->getMethodFromEm2().
Note: But I wouldn't prefer above solution unless there is really a need. I would rather create a service layer which has Doctrine Entity Manager as Dependency Injected. This service layer will connect to all the repositories and collect final result whatever you want to achieve (to be used in the controller). This way, the code will be much cleaner and testable as well.
Hope this helps.
Repositories are class (so entity) reserved. If you inherit from super classes (even if those classes doesn't inherit directly, but repos can), than you can make your repository (CategoryRepository) extended by other two (one extend the other, since PHP doesn't allow more than one class extension).
Pretty much something like that
class NestedTreeRepository extends SortableRepository
{
}
class CategoryRepository extends NestedTreeRepository
{
}
don't know if this fits your needs, but this a way (and I'll not surprised if is the only one) for realize what you're trying to do here

Flex: load parent class into module

My main application contains a ClassA. The main application then loads a module and in that module I would like would to do:
var classA:InterfaceClassA = new ClassA();
It compiles fine but I get this warning:
Warning: YourApplication is a module or application that is directly referenced. This will cause YourApplication and all of its dependencies to be linked in with module.YourModule:Module. Using an interface is the recommended practice to avoid this.
I can't use an interface to generate the new instance, so what is the correct way to do this?
I found an answer in Accessing the parent application from the modules . I created a helper class in the main Application that contains instances of the classes I want to access. In the module I then use:
parentApplication.myModuleHelper.**myClassInstance**.myMethod();
for instance methods and for static class level methods I use:
parentApplication.myModuleHelper.**MyClassInstance**.myMethod()
To get an instance of my class in a module I use this in MyModuleHelper
public function getFullScreenUtil(iFullScreenUtil:IFullScreenUtil , iSystemManager:ISystemManager):FullScreenUtil {
return new FullScreenUtil(iFullScreenUtil , iSystemManager);
}
and this in MyModule:
var _fullScreenUtil:* = parentApplication.moduleHelper.getFullScreenUtil(this , systemManager);
which is all I need for now. I am not sure how I could cast the result of getFullScreenUtil(..) to an actual instance of FullScreenUtil but I expect that it can not be done in modules. Maybe using an interface would provide the solution to that.

Virtual methods still required when using Moq?

We're using Moq and I was wondering what the current role of virtual methods were in it-- in the post below dated 2008 it's clear you had to mark your methods as virtual in order for Moq to work (or inherit from an interface.)
Moq discussion
However, is this still the case in .Net 4.5, that you're required to use virutal methods in the class you want to mock? And does this also hold true when you create a wrapper class around a static method-- the wrapper class either inherits from an interface or the method in question needs to be marked virtual?
This hasn't changed in .NET 4 or 4.5. As the link you provided explains, Moq uses Castle Windsor Dynamic Proxy to generate a type derived from the type you wish to mock. Therefore, the standard rules of inheritance apply. The derived type generated by Moq can only intercept calls to methods that any normal derived class can override.

Resources