How to use a custom module in a custom theme?
I've created a class.testmodule.php
that I've put in /themes/mytheme/modules
at first, but using {module name="TestModule"}
gave me a "Error: TestModule doesn't exist" message.
I've tried it again after I moved that file to /themes/mytheme
, but that wasn't helpful. I had no luck with that, too.
In class.theme.php where the error is generated, I've added a small decho(get_declared_classes());
in order to see if I had a dumb typo, but the sad truth is, that my module isn't loaded. To I have to include it "manually" in the themehooks or is there a better place than I have chosen where it would be autoloaded?
Best Answers
-
vrijvlinder MVP
-
nonce ✭
apparently you asked the question before as indicated by the above answer. but you are still not satisfied.
here is more info to help you and your kinfolk.you said: I'm more interested in where the class auto loading happens.
I have looked at the code, read the tutorials, and searched the discussions.
first - lets give some information.
look in your cache folder.
notice all the files.
some start with a, p, or even possibly t.a is for applications
p is for plugins
t is for themesdashboard, core, library should all be self explanatory. these map names with folder location.
you will see a variety of classes, modules, and models.if you don't see your module or class it is not mapped or registered in the cache. simple enough.
now a code walk though for you.
modules from themes are not mapped or cached in the ini files as are library modules and plugin modules. p is for plugin d is for dashboard,
here is a code walk through. I won't answer why it is not part of the core, you can debate among yourselves.
the index.php is called first and contains
// Include the bootstrap to configure the framework.
require_once(PATH_ROOT.'/bootstrap.php');the bootstrap.php is called and Theme Startup and Autoloading.
// Themes startup
Gdn::themeManager()->start();
Gdn_Autoloader::attach(Gdn_Autoloader::CONTEXT_THEME);now it looks at the autoloader.php after theme manager functions are available.
in the autoloader.php
there are three case statements referring to plugins, apps, and themes.
you will see the plugins are "mapped and registered" via RegisterMap in in attach method
you will see the apps are "mapped and registered" via RegisterMap in in attach application method
you will see the themes are essentially ignored and just a break appears.simply
case self::CONTEXT_THEME:
break;if you look at apps you see
$AppModules = combinePaths(array($ApplicationPath."/modules")); self::registerMap(self::MAP_LIBRARY, self::CONTEXT_APPLICATION, $AppModules, array( 'SearchSubfolders' => false, 'Extension' => $Application, 'ClassFilter' => '*module' ));
fot themes, if you modified the core you would add
self::RegisterMap(Gdn_Autoloader::MAP_LIBRARY, Gdn_Autoloader::CONTEXT_THEME, 'themes/'.Gdn::themeManager()->currentTheme );before the break statement.
but you could also use a similar RegisterMap method for your theme Gdn_Autoloader::RegisterMap .... in conf/bootstrap.after.php, the thememanager is processed or by themehooks, which is what you asked in the first place and is answered by previous poster. Themehooks is a better approach, alternate method is a teaching experience.
you can use getallclasses to debug, but you could have looked at the ini files and their mappings.
a_dashboard_library_map.ini
a is for application
dashboard related
libraryp_core_library_map.ini
p is for plugin related modules, classes and models.
notice how plugins that are not enabled have modules mapped in the cache.
after you use the register map for your theme you will notice
t_library_map.ini if you chose library as the Map Type and Context as Theme.
I hope this helps you in one way or another.
3
Answers
I added my modules to my theme in a modules folder in views folder.
For tpl you may need to use this in the themehooks
❌ ✊ ♥. ¸. ••. ¸♥¸. ••. ¸♥ ✊ ❌
Thanks, @vrijvlinder. But if I add a custom smarty function, the module and another custom smarty function, I'd have to insert a custom fireEvent in order to use your recommendation. I think it is a workaround which would be okay to use but I'm also technically interested.
I'm more interested in where the class auto loading happens. Should/Must the theme folder be added somewhere or must some mechanism be used for themes, too? Or is this overkill? Do I have to auto load by myself out simply include it? I haven't tested it, but would it be "early" enough to include it in base_render_before or what would be the best place to take care for that?
For one, I think the modules folder need to be in the views folder.
❌ ✊ ♥. ¸. ••. ¸♥¸. ••. ¸♥ ✊ ❌
I think the views folder can be used if I override an existing module. I've tried to copy my module there but that was not working, either...
Not sure if you read this
https://vanillaforums.org/discussion/comment/220751#Comment_220751
or
https://vanillaforums.org/discussion/30730/adding-a-custom-module-to-a-theme
❌ ✊ ♥. ¸. ••. ¸♥¸. ••. ¸♥ ✊ ❌
apparently you asked the question before as indicated by the above answer. but you are still not satisfied.
here is more info to help you and your kinfolk.
you said: I'm more interested in where the class auto loading happens.
I have looked at the code, read the tutorials, and searched the discussions.
first - lets give some information.
look in your cache folder.
notice all the files.
some start with a, p, or even possibly t.
a is for applications
p is for plugins
t is for themes
dashboard, core, library should all be self explanatory. these map names with folder location.
you will see a variety of classes, modules, and models.
if you don't see your module or class it is not mapped or registered in the cache. simple enough.
now a code walk though for you.
modules from themes are not mapped or cached in the ini files as are library modules and plugin modules. p is for plugin d is for dashboard,
here is a code walk through. I won't answer why it is not part of the core, you can debate among yourselves.
the index.php is called first and contains
// Include the bootstrap to configure the framework.
require_once(PATH_ROOT.'/bootstrap.php');
the bootstrap.php is called and Theme Startup and Autoloading.
// Themes startup
Gdn::themeManager()->start();
Gdn_Autoloader::attach(Gdn_Autoloader::CONTEXT_THEME);
now it looks at the autoloader.php after theme manager functions are available.
in the autoloader.php
there are three case statements referring to plugins, apps, and themes.
you will see the plugins are "mapped and registered" via RegisterMap in in attach method
you will see the apps are "mapped and registered" via RegisterMap in in attach application method
you will see the themes are essentially ignored and just a break appears.
simply
case self::CONTEXT_THEME:
break;
if you look at apps you see
fot themes, if you modified the core you would add
self::RegisterMap(Gdn_Autoloader::MAP_LIBRARY, Gdn_Autoloader::CONTEXT_THEME, 'themes/'.Gdn::themeManager()->currentTheme );
before the break statement.
but you could also use a similar RegisterMap method for your theme Gdn_Autoloader::RegisterMap .... in conf/bootstrap.after.php, the thememanager is processed or by themehooks, which is what you asked in the first place and is answered by previous poster. Themehooks is a better approach, alternate method is a teaching experience.
you can use getallclasses to debug, but you could have looked at the ini files and their mappings.
a_dashboard_library_map.ini
a is for application
dashboard related
library
p_core_library_map.ini
p is for plugin related modules, classes and models.
notice how plugins that are not enabled have modules mapped in the cache.
after you use the register map for your theme you will notice
t_library_map.ini if you chose library as the Map Type and Context as Theme.
I hope this helps you in one way or another.
You must be a reincarnation of someone I know... because you certainly do not "flounder" around...and give concise and enlightening answers... reminds me of the old days when I first started here... thanks for that
❌ ✊ ♥. ¸. ••. ¸♥¸. ••. ¸♥ ✊ ❌
That's kind of embarrassing. Sorry for repeating myself and forgetting good advices
It's never too late to learn from your own questions.... :P
❌ ✊ ♥. ¸. ••. ¸♥¸. ••. ¸♥ ✊ ❌
Nope, I'm only forgetful.
You bet! Now I understand why theme classes are not autoloaded!
If anyone is interested: think of a theme with a
class.examplemodule.php
and a mobile theme withclass.examplemodule.php
. Classes are mapped when they are accessed first. So depending on the users client who visits the site first, it would be either mapped to the module in the mobile or in the desktop version. The current implementation must be extended to always take care of the current theme of the current user.The need for making this changed hasn't aroused by now, so implementing something without needing it is not the best idea.
My learning from that: if you use classes in your theme, give them unique names. If your theme is called "groovy" and you would like to create "fancymodule", consider naming it "groovyfancymodule".