Silverstripe - Turn modules on or off in config - yaml

Is it possible to activate or deactivate modules based on entries in either config.yml or _config.php?
Say I've built an Image Gallery module but don't want it showing on the site yet, can it be deactivated in the config files?

Only if the module has provided functionality to do so.
You can add your own private static $enable_module = true
class MyClass extends Object
{
private static $enable_module = true;
public function doMyThing()
{
if (!Config::inst()->forClass('MyClass')->enable_module) {
return false;
}
// do stuff here
}
}
then you can disable it via YML
MyClass:
enable_module: false
would disable it.
For templates you could add
public function getGalleryEnabled() {
return Config::inst()->forClass('MyClass')->enable_module;
}
to your Page_Controller class and then
<% if $GalleryEnabled %><% include MyGallery %><% end_if %>
The best practice is: never develop on the live site

SilverStripe scans all directories in webroot for modules. If you place a file called manifest_exclude in any directory, it won't be scanned and not included; the autoloader won't find it and you cannot call your class without including the file manually.

Related

Activate two add-ons on prestashop

I want to activate two add-ons on prestashop but i cant activate both i get this error
Cannot enable module blockproductsbycountry. Unable to install override: The method getProductProperties in the class Product is already overridden by the module dynamicproduct
the path
public_html/override/classes/Product.php
provider->isAfter1730()) { $id_product = (int) $row['id_product']; $dynamic_config = classes\models\DynamicConfig::getByProduct($id_product); if ($dynamic_config->active) { $displayed_price = classes\models\DynamicConfig::getDisplayedPrice($id_product); if ($displayed_price || $dynamic_config->display_dynamic_price) { $module->calculator->assignProductPrices($row, $displayed_price, $result); } } } return $result; } }
This happens when a method of a class is overriden by both modules at the same time.
There is no automatic solution for this: you will have to check both overrides and manually merge the code back into the main Prestashop folder (/override/classes/Product.php).
After that you will have to remove the overridden method from the installer of both modules so that you can install/activate/deactivate them as needed without having errors.

ExcelDna - Excel can't access function in base class

When Excel tries to call a method in a abstract base class i get a Run-Time error
"Cannot run Marco 'MarcoName'. The macro may not be available"
I can run code from the super class.
The code is similar to this
public abstract class MyBaseClass
{
public static bool MyMethod(string path)
{
if(Valid(path))
{return true;}
return false;
}
}
This code is in a separate assembly imported via a nuget package
The calling code is similar to the below
public class MyClass : MyBaseClass
{
public static bool MyOtherMethod()
{
return true;
}
}
Marking the methods with the "[ExcelFunction]" attribute has no effect.
I am loading the xll file like so,
Application.RegisterXLL (path)
I call the method like so,
Application.Run("MyMethod", path)
Only code in assemblies that are included in the <ExternalLibrary ... /> list in the .dna file are scanned for functions to register. Maybe your external assembly is not mentioned there.
Also, abstract types were not always considered. It looks like this changed at some point, if I look at the code that scans the assemblies here: https://github.com/Excel-DNA/ExcelDna/blob/57c2d0a499a044f6cd1c4ae2c9fbf5b084159dea/Source/ExcelDna.Integration/AssemblyLoader.cs#L93
So it might depend on your Excel-DNA version too.
Easiest might be to have a class with all the functions you want to export, where you can add the Excel-specific attributes (<ExcelFunction .../>) and just forward the calls internally.

UWP - Inherit from Base Page C#

I'm one of the many windows app developers. I'm sure someone other ran in this problem too. I want to have a base page (c#) where I add methods and use it in some pages without coding it over and over.
I've tried it like this:
Basicpage.cs:
public class BasicPage : Page
{
public void Test() {
}
}
SettingsPage.xaml.cs:
public sealed partial class SettingsPage : BasicPage{
public SettingsPage () {
InitializeComponent();
}
}
On the bold "BasicPage" there are the errors:
Base class of "...SettingsPage" differs from declared in other parts
and
Base type 'BasicPage' is already specified in other parts
Does someone know a solution?
I assume SettingsPage has a XAML part, which also needs to be derived from BasicPage:
<local:BasicPage x:Class="MyNamespace.SettingsPage" ...>
<!-- settings page content -->
</local:BasicPage>

RazorEngine WebApiTemplateBase #Url.Content()

How can I get #Url.Content() working in my _Layout.cshtml when RazorEngine is being used from ASP.NET Web API?
RazorEngine (v.3.7.2) only deals with the Razor syntax and not the additional helper methods like #Html or #Url. These can be added by extending the TemplateBase<> and setting it in the configuration.
There are code examples in some old issues: #26, #29; in an unreleased, incomplete piece of code in MvcTemplateBase.cs; and in the documentation for Extending the Template Syntax.
My problem is I'm using ASP.NET Web API (v.1) which won't have HttpContext.Current (nor should it). I want to provide a UrlHelper as I want to use its Content() method but it needs to be instantiated with the HttpRequestMessage which won't be available.
Perhaps there's no way to get #Url helper methods for my compiled layout. Perhaps I need some other way of getting the absolute path from the virtual path. It seems I'd still need some way of checking the Request though.
A way to get this working is to follow the direction set by Extending the Template Syntax and use VirtualPathUtility.ToAbsolute() in a helper method.
using System.Web;
using RazorEngine.Templating;
namespace MyNamespace.Web
{
public abstract class WebApiTemplateBase<T> : TemplateBase<T>
{
protected WebApiTemplateBase()
{
Url = new UrlHelper();
}
public UrlHelper Url;
}
public class UrlHelper
{
public string Content(string content)
{
return VirtualPathUtility.ToAbsolute(content);
}
}
}
Set up the TemplateService configuration with this extension of the TemplateBase<>.
var config =
new RazorEngine.Configuration.TemplateServiceConfiguration
{
TemplateManager = new TemplateManager(),
BaseTemplateType = typeof(WebApiTemplateBase<>)
};

Sharing Controllers and Views with Multiple Web Applications

I would like to break out my controllers and views into separate class libraries so they can be reused in multiple ASP.NET MVC 3 applications. The controllers part was not an issue when using a separate assembly, however getting the view engine to locate the view was.
I ended up using Compile your asp.net mvc Razor views into a seperate dll.
Is there an easier way that I missed?
I have modified the idea posted here, to work with MVC3. It was pretty fast and easy. The only minor drawback is that shared views need to be embedded resources, and therefore, compiled.
Put your shared views (.cshtml, .vbhtml files) into a library project. (I also have some shared controllers in this project.) If you want to use the _Layout.cshtml from your application, make sure you include a _ViewStart.cshtml, that points to it, in with your shared views.
In the library project, set all of your views' Build Action properties to Embedded Resource.
In the library project add the following code which will write the contents of your views to a tmp/Views directory.
.
public class EmbeddedResourceViewEngine : RazorViewEngine
{
public EmbeddedResourceViewEngine()
{
ViewLocationFormats = new[] {
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx",
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml",
"~/tmp/Views/{0}.cshtml",
"~/tmp/Views/{0}.vbhtml"
};
PartialViewLocationFormats = ViewLocationFormats;
DumpOutViews();
}
private static void DumpOutViews()
{
IEnumerable<string> resources = typeof(EmbeddedResourceViewEngine).Assembly.GetManifestResourceNames().Where(name => name.EndsWith(".cshtml"));
foreach (string res in resources) { DumpOutView(res); }
}
private static void DumpOutView(string res)
{
string rootPath = HttpContext.Current.Server.MapPath("~/tmp/Views/");
if (!Directory.Exists(rootPath))
{
Directory.CreateDirectory(rootPath);
}
Stream resStream = typeof(EmbeddedResourceViewEngine).Assembly.GetManifestResourceStream(res);
int lastSeparatorIdx = res.LastIndexOf('.');
string extension = res.Substring(lastSeparatorIdx + 1);
res = res.Substring(0, lastSeparatorIdx);
lastSeparatorIdx = res.LastIndexOf('.');
string fileName = res.Substring(lastSeparatorIdx + 1);
Util.SaveStreamToFile(rootPath + fileName + "." + extension, resStream);
}
}
I'm using Adrian's StreamToFile writer, found here.
In the Global.asax.cs of your application add:
.
public static void RegisterCustomViewEngines(ViewEngineCollection viewEngines)
{
//viewEngines.Clear(); //This seemed like a bad idea to me.
viewEngines.Add(new EmbeddedResourceViewEngine());
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
RegisterCustomViewEngines(ViewEngines.Engines);
}
Take a look at mvc contrib's portable areas:
http://www.lostechies.com/blogs/hex/archive/2009/11/01/asp-net-mvc-portable-areas-via-mvccontrib.aspx
They were made specifically for this purpose. If you go that road, it is less code you have to mantain ;-)
Just a few additions to Carson Herrick's excellent post...
You will need to resolve a few of the references (you will need to include System.Runtime.Remoting into your project).
Utils.SaveStreamToFile needs to be changed to ->
System.Runtime.Remoting.MetadataServices.MetaData.SaveStreamToFile(resStream, rootPath + fileName + "." + extension);
You may get the error - The view must derive from WebViewPage, or WebViewPage<TModel>. The answer is here: The view must derive from WebViewPage, or WebViewPage<TModel>
When you deploy the project, it is highly likely you will get an error when you load the project. You need to give the APP POOL you are using (full) rights to the folder.

Resources