New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Plugins can provide their own config files #7117
Conversation
|
||
private function addPluginConfigs(ContainerBuilder $builder) | ||
{ | ||
$plugins = Config::getInstance()->Plugins['Plugins']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't use the plugin manager here because getActivatedPlugins()
returned an empty array (plugins weren't loaded yet).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we load plugins before that or so? We should not really include configs of not activated plugins. Also in tracker mode we have much less plugins that need to be loaded/activated etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is how FrontController::init()
goes:
$tmpPath = StaticContainer::get('path.tmp');
$directoriesToCheck = array(
$tmpPath,
$tmpPath . '/assets/',
$tmpPath . '/cache/',
$tmpPath . '/logs/',
$tmpPath . '/tcpdf/',
$tmpPath . '/templates_c/',
);
Filechecks::dieIfDirectoriesNotWritable($directoriesToCheck);
$this->handleMaintenanceMode();
$this->handleProfiler();
$this->handleSSLRedirection();
Plugin\Manager::getInstance()->loadPluginTranslations();
Plugin\Manager::getInstance()->loadActivatedPlugins();
Is it safe to move Plugin\Manager::getInstance()->loadActivatedPlugins();
before the "is writable" check? If yes then that would allow to load the plugins before the container is created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure, it should be safe. Needs to be tested and checked what is done in there, only had a rough look.
Also we need to make sure that during this process DI is not used in the background eg by Config etc? Otherwise it might end in a problem again...
Maybe it makes sense to load "global.php" first... while loading/activating the plugins we also load their definitions. Might be easiest solution that should work and also makes sure we load it only if needed eg while tests are run etc. On "deactivate Plugin" we could maybe unload the definition - if possible. Not really needed though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Loading config files (or even changing definitions) after the container has already been used is really risky. If any service or value has already been resolved and injected somewhere, it will not be replaced.
E.g. the logger is injected somewhere, then a plugin changes the logger: the old one is still injected in some places… Leading to inconsistent services.
It might not be a problem directly, and the logger might not be so critical, but it's calling for trouble later with more serious components or config values.
Ideally the container should be built in one step and entries should not be changed after that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually funny thing, path.tmp
is an example of something a plugin might change: the CloudAdmin plugin could override that to add the "instance ID" to separate data for each instance.
Today it's using this "instance ID" hack but in the future it could be the plugin that handles that using the container.
Quick n dirty example to illustrate:
// global.php
'path.tmp' => 'tmp',
// CloudAdmin/plugin.php
'path.tmp' => 'tmp/' . $instanceId,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the diff to load plugins before the container.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the diff to load plugins before the container.
It looks like the diff is not updated though? it says Config::getInstance()->Plugins['Plugins'];
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep after the discussions (below) I went back to the initial solution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not yet loaded in the correct order, is it?
|
||
foreach ($plugins as $plugin) { | ||
$file = Manager::getPluginsDirectory() . $plugin . '/plugin.php'; | ||
if (file_exists($file)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the config already cached or do we do this on each request? Can we name it maybe config.php
or so? Would be maybe more intuitive for developers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said in the PR config.php
wasn't possible.
There is no cache for now (well there is the ArrayCache
but of course not persistent between requests).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to have a cache at some point, especially re tracking.
Can we maybe rename/move the existing Config
classes? Or check whether that file actually returns something and if not, ignore it? We will probably have this convention for a while so might be worth it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could the file be located in a config folder, ie plugins/MyPlugin/config/config.php
? Ie, mirror the top-level folder structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've implemented plugins/MyPlugin/config.php
, see the diff. Not the most efficient piece of code ever but I guess the opcache should make it a non-problem.
I like having config.php
at the root of the plugin. But if the change is really not efficient, we could move it to a sub-directory.
But for 3.0 we could say config.php
must be a config file, move your class elsewhere. In the meantime we keep BC. So the current Config
classes would be sort of "deprecated".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@diosmosis haven't thought of that. Actually I'd be 👍 We always try to use same structure already (eg with other folders Columns
, tests/UI
and tests/*
, Tracker
, Visualization
, ... ) so would make sense. I'm sure we'll have a generator for this at some point so it wouldn't matter when it is in a config
directory. Would also allow to add maybe other config entries if needed. Maybe the config
folder would be also useful if we allow to provide something like config-dev.php
or config/environment/dev.php
that will be automatically used for development etc?
/config.php
would be otherwise ok for me as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would also allow to add maybe other config entries if needed. Maybe the config folder would be also useful if we allow to provide something like config-dev.php or config/environment/dev.php that will be automatically used for development etc?
Great point, I'm +1 with that idea then, I'll move again to config/config.php
.
FYI it turns out there's the same problem than with the FrontController all over the place: there is no guarantee that plugins are loaded when the container is called. I'm trying to find a proper solution to always init the plugins before the container in all environments (web, console, tests, archive.php, tracker, …) |
After some discussions:
TL/DR: problems should be solved! |
984e5e1
to
851a567
Compare
Just to be sure we do load only the config for activated plugins right? The wording that we currently have is a bit confusing since loaded can be different to activated |
Ah right. Basically I'm including config file for these public function loadActivatedPlugins()
{
$pluginsToLoad = Config::getInstance()->Plugins['Plugins'];
$this->loadPlugins($pluginsToLoad);
} |
Yep. I was thinking a check whether they are also installed might be needed but a plugin can't be activated without being installed so should be all good |
Hey @tsteur could you confirm/merge this one? (looks good to me) |
I think this part is missing to make sure plugin configs are loaded in correct order: https://github.com/piwik/piwik/blob/2.11.0-b3/core/Plugin/Manager.php#L1267-L1276 Also it would be nice to have it cached so that we do not do the |
851a567
to
a028d17
Compare
$plugins = $this->sortPluginsSameOrderAsGlobalConfig($plugins); | ||
|
||
return $plugins; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tsteur I have added this method but it kinda duplicates this one just above:
public function getActivatedPlugins()
{
return $this->pluginsToLoad;
}
However replacing the existing method by the one I added just blew up everything… I think it's simply that the existing one has a bad name (it doesn't return the activated plugins, it returns the ones the plugin manager is supposed to load). I could rename it from getActivatedPlugins()
to getPluginsToLoad()
if it makes the diff any better.
Done, please see the inline comment for more details. |
Plugins can provide their own config files
Is it actually done? Not sure, I linked to |
Yes I figured that's because |
In case someone messes around with the config or whatever it would maybe make sure Piwik still works. I reckon it is not necessarily needed though it could be a nice to have. Also not sure for what it will be used in the future... Up to you |
I've updated the code on master. |
See #6609 and #7115
Plugins can provide DI config by putting it in
plugin.php
.The file name is completely arbitrary and can be changed… I first went with
config.php
but some plugins already have aConfig
class.