Silverstripe - Custom changes to a module - module

Not sure where to look for this. I want to make changes to a Silverstripe module I added to my site with composer but I don't want the custom code to be overwritten when I update the module at a later stage.
How can I make a few changes to some of the code without editing the core files? The code in question is in a function that is in a controller.

It definitely depends on your case.
If you want to add some custom methods use an Extension(see Simon's
answer)
If you want to add some database fields or relations, a DataExtension
is your friend
If the module is extensible and provides hooks, you
can change behaviour in your (you guessed it) Extension. Look for
$this->extend('functionName') in the module, you can modify stuff
in a method functionName() in your Extension
But sometimes it's a
bug or the module doesn't provide a hook you can use, then you have
to subclass the class and tell SilverStripe to use your Subclass instead:
class MySubClass extends SomeClass
{
public function doSomething()
$something = parent::doSomething();
//your changes
return $something;
}
}
You just need your changes and overwritten methods in your subclass, no need to copy all stuff in your subclass. This way you'll get most module updates later on.
Then you need to configure Injector to use your MySubClass instead of SomeClass in your config.yml:
Injector:
SomeClass:
class: MySubClass

You can make your own extension to it, e.g. class MyModuleExtension extends Extension
And override/edit/change code in there.
In your config.yml, register the new extension like so:
OriginalController:
extensions:
- MyModuleExtension

Related

How to move a function from one Kotlin class to another using IntelliJ?

I'm using IntelliJ IDEA to refactor some Kotlin code. I have two classes in the same file and I want to move a function from one class to another using Refactor -> Move (F6), but that doesn't work, and I get tooltip message that says: "Cannot perform refactoring. Move declaration is only supported for top-level declarations and nested classes".
Am I doing something wrong? Or that refactoring is simply not supported?
[edit1] I tried to do the same operation with Java classes and everything works perfectly; so why this is not allowed for Kotlin?
[edit2] I thought that the problem is only when to two classes are in the same file, but it turns out that is not possible to move a function between classes in separate files!
It's a well-known Kotlin-only problem.
in IDEA (both free and paid editions);
in Android Studio.
Official ticket
There is an easy, but slightly janky, work around.
You just need to wrap the function you want to move in a class:
class TopLevelClass {
fun functionToMove() {
//...
}
}
wrap it in a new class
class TopLevelClass {
class TemporaryMoveClass{ /** you can now move this entire new class */
fun functionToMove() {
//...
}
}
}
and after you do the refactor, delete the temporary wrapper class you created.
The janky part is that you need to replace all instances of functionToMove() with NewTopLevelClass.functionToMove() yourself.
One of the major benefits of doing it this way, rather than just cut and pasting it yourself, is that as soon as you wrap it in the TemporaryMoveClass it will tell you any parameters you need to introduce(Refactor>Extract>Parameter). And then you can do that inside the original TopLevelClass before you move it. (this preserves the types of any TopLevelClass properties you were using, and automatically introduces the new parameter(s) into the existing function calls)

Changing the implementation of Objective C method in Swift subclass

I am using an external library in my project. It is integrated via CocoaPods. I have access to the source code. The library is working well, but I need some modifications at some places in order for it to serve my purposes. It is written in Objective C. My project is in Swift.
I need to change the implementation of one method in the library. The problem is it is in the .m file and uses a lot of stuff declared only in the .m file. For example:
-(NSString*)methodToChange
{
NSArray<NSNumber*>* data = [self someInternalMethod:1];
uint value = data[0].unsignedIntValue;
return [self anotherInternalMethod:value];
}
I tried subclassing it like this:
class MySubclass : MySuperclassWithMethodToChange {
override var methodToChange: String {
//trying to use someInternalMethod and anotherInternalMethod
//unsuccessfully because they are not visible
}
}
The internal methods are using and modifying properties from the .m file that are also not accessible. Is there any way to solve this?
I would suggest forking the original library repository and making the necessary changes in your fork. You can then have your Podfile point to that. If your changes could be useful to others, make them in a way that doesn't break existing functionality and contribute them back to the library by opening a pull request.
If the original library gets updated later, you will have to merge those changes from the so-called "upstream" repository into yours. This does not happen automatically, so you'll have full control (and responsibility) over that process. See https://help.github.com/en/articles/syncing-a-fork for how this would look like.

Xcode can't see a Class Extension Header even though I've imported it

After going round in circles for ages on this one, I'm asking and self-answering for future readers:
Create a class in Xcode (.h and .m)
Create a Class Extension in Xcode (.h)
...do something in that class extension...
Import the Class Extension to the class it extends (in the .m)
Import the Class Extension to a different class
Reference something - anything - in that different class
...Xcode compiler error: can't find / see / act upon the contents of the Class Extension
Took me ages and ages to see this, I couldn't find any hits on SO, but the cause is:
Issue in Apple's "create class extension" template, IF the project was ORIGINALLY created as a static-library:
By default, instead of #import'ing the class you're extending, it #import's the library's global file - which might be what you want (if you want to export this class header), but which may or may not contain that header.
To fix it, manually #import the original class's header into the class-extension, and your sanity will be restored.

How to define methods and properties only visible within an objective-c framework?

I am trying to write an objective-c framework and I would like to have methods and properties visible only within the framework. I know I could define them in a class extension inside the implementation file but then they will not be accessible by other classes.
One way I was thinking to do it was to define a category for example MyClass+Internals and make that header private. but make the MyClass.h header public. I was wondering if there was a better way of doing this. Also, I'm not sure you can define properties within a category I thought it was only methods. Thanks for any suggestions or feedback.
Say you have a class named "Foo", then in "Foo_Framework.h", create:
#interface Foo()
#property ....;
- .... method ....
#end
Then, make sure that "Foo_Framework.h" is imported before the #implementation Foo. That'll cause the class Foo to be compiled with the extended interface found in said header file. That header can then be used throughout your framework. Just don't make it available outside said framework.
You are correct that you can't declare properties (that are synthesized) in a category. That was one of the primary motivations for the creation of class extensions, of which the above is an example.

Why Can't I Inherit IO.Directory?

Why can't I create a class in VB.NET that inherits System.IO.Directory? According to Lutz Roeder, it is not declared as NotInheritable!
I want to create a utility class that adds functionality to the Directory class. For instance, I want to add a Directory.Move function.
Please advise and I will send you a six pack. OK nevermind I'm not sending you anything but if you come to the bar tonight I will hook you up and then beat you in pool.
From the Meta Data of .NET
namespace System.IO
{
// Summary:
// Exposes static methods for creating, moving, and enumerating through directories
// and subdirectories. This class cannot be inherited.
[ComVisible(true)]
public static class Directory
You cannot inherit from a Static Class.
Are you using C# 3.0 VB.NET 2008 -- then you could add an Extension Method
If you use the DirectoryInfo class, you will have access to a MoveTo function.
EDIT: I'll correct myself... The static Directory class already has a Move method.
I'd guess that Reflector isn't picking up the sealed attribute correctly for VB (or perhaps just not displaying it properly). If you look at the IL, it is sealed:
class public abstract auto ansi sealed beforefieldinit Directory