Skip to content
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

First step to addons support #672

Closed
wants to merge 10 commits into from
Closed

First step to addons support #672

wants to merge 10 commits into from

Conversation

JanJakes
Copy link

@JanJakes JanJakes commented Jun 2, 2012

This is a first step to add addons support to Nette, no BC breaks.

It solves the definition, naming and installation of addons and we can have access to it's directory (for resources, etc.).

Next steps should be:

  • routing to addon's Presenters, loading addon's templates
  • some 'sugar' like addons.neon and some automatic behaviour following suggested conventions

How does it work at the moment?

Every addon is a subclass of Nette\Addons\Addon. It has some methods to resolve it's name and path. The compile() function is used to register compiler extensions. The basic approach is similar to Kdyby, but simplified.

1. Addon definition

Every addon must be a subclass of Nette\Addons\Addon.

The simplest addon class can be empty:

class TestAddon extends Nette\Addons\Addon
{
    // the default addon name will be resolved from the class name - "test"
}

The addon's creator can also specify it's default name:

class TestAddon extends Nette\Addons\Addon
{
    protected $name = 'someName';
}

User of the addon can always overwrite its name (see installation).

We can register compiler extensions in the compile function:

class TestAddon extends Nette\Addons\Addon
{
    public function compile(Nette\Config\Configurator $configurator, Nette\Config\Compiler $compiler, AddonContainer $addonContainer)
{
        $compiler->addExtension($this->name, new TestExtension);
    }
}

We can also use Nette\Application\Application events in the addon:

class TestAddon extends Nette\Addons\Addon
{
    public function startup() {}
    public function request(Nette\Application\Request $request) {}
    public function response(Nette\Application\IResponse $response) {}
    public function error(\Exception $e) {}
    public function shutdown(\Exception $e = NULL) {}
}

2. Installation (in bootstrap.php)

$configurator->registerAddons(array(
    new TestAddonPack\ConsoleAddon\ConsoleAddon
));

Addon can be also named by user:

$configurator->registerAddons(array(
    'myConsole' => new TestAddonPack\ConsoleAddon\ConsoleAddon
));

If addon is not named by user, it can have a default name given by it's creator. If there is no one, the addon will take the name from the class name (ConsoleAddon will be "console").

3. Compiler extensions

Compiler extension can be registered in the addon class in a function compile(). The suggested convention is using the addon name as a prefix:

    public function compile(Nette\Config\Configurator $configurator, Nette\Config\Compiler $compiler, AddonContainer $addonContainer)
{
    $compiler->addExtension("$this->name.one", new OneExtension);
    $compiler->addExtension("$this->name.other", new AnyOtherExtension);
}

All the service definitions should be named with $this->prefix().

If we use this conventions, user is able to rename the prefix of addons services as he needs.
This could, however, bring a problem when we create an addon that refers some services from another addon. To find out the name that user has chosen for addon we can use the AddonContainer:

$addonContainer->getAddonByType('Vendor\TestAddon\TestAddon')

Inside a compiler extension class we can simply use:

$name = $this->parameters['addons']['Vendor\TestAddon\TestAddon'];

4. Using addons, AddonManager

Many addons will add it's function to the DI container as a new services - then we can use them as any other services.

If we need to get some information about the addon (name, path, etc.), we can use service addonManager. For example in a Presenter class:

$addon = $this->context->nette->addonManager->getAddon('testAddon');

Or:

$addon = $this->context->nette->addonManager->getAddonByType('Vendor\TestAddon\TestAddon');

Etc. (See the AddonManager class methods.)

Then we can get desired information:

$addon->getName();
$addon->getPath();
$addon->getNamespace();

@f3l1x
Copy link
Member

f3l1x commented Feb 20, 2013

To uz nejspis nema vyznam v dnesnim svete extensions :)

@enumag
Copy link
Contributor

enumag commented Feb 20, 2013

@f3l1x Use english please ;-)

@JanJakes I don't like the fact that all addons are called on every $application event regardless of whether the addon actually needs to be called. It would be better to let the addon register it's own events if needed.

Also I have to aggree with @f3l1x.

@vojtech-dobes
Copy link
Contributor

There has been huge discussion on this topic - http://forum.nette.org/cs/10875-nette-addons-konvence-a-architektura-aplikace?p=2. I also agree with closing, because all these things can be more flexibly accomplished via CompilerExtension.

@JanJakes
Copy link
Author

First of all I suggest to all of you to carefully read the above mentioned topic. Then to study at least Symfony, RoR or any other framework that has some solution to addons and modularity.

I agree with @enumag that the events can be solved other way (but one can find that by reading the topic and it's not the most important thing about this PR).

I totally disagree with all of you about the extensions. Now it makes much more sense than ever before. The new addon site is in progress, people started to make new extensions, datagrids, etc., but there's absolutely no support for this from the framework side, there's a huge mess in the extensions and their installation is usually complicated and "dirty". Compiler extension is a very nice thing but it's NOT a solution to addons and modularity. Again, it's all already discussed here http://forum.nette.org/cs/10875-nette-addons-konvence-a-architektura-aplikace and until this is solved, Nette is just a mixture of a very nice tools but not a mature framework.

@enumag
Copy link
Contributor

enumag commented Feb 21, 2013

@JanJakes You can easily make an extension from THIS very PR you know. In any case it would be better to register addons in neon than Compiler::registerAddons which is easy to do by extention.

Also if addon has it's own presenters etc., how are CSS, JS, Images, etc. solved? It was surely discussed before, I just don't have time to read the entire topic about this.

@JanJakes
Copy link
Author

@enumag This PR is just a "first step" and a kind of RFC - something that came from the discussion on the forums and is intended to be discussed. It is (probably) at the moment not possible to make such thing just an extension. Simply because of the things that are mentioned on the forums and that you've mentioned too - Compiler extension is just a complier extension, when we need some solution for any type of addon, we need to have access to it's CSS, JS, etc., routing on it's Presenters, etc. Solutions to these are discussed in the topic.

CSS, JS, etc. is a very complicated problem. What I've proposed was the first and most basic step - each addon would provide paths to it's assets in some standardized or recommended way. Then it would be up to anybody if he would just copy them to public directory, use WebLoader or Assetic, etc. The point was just to define some basic rules, the smallest possible set of rules that are necessary and leave the rest on the addons. For details and solutions to assets see the forum, Symfony, Assetic or Pythons's Webassets.

@dg dg force-pushed the master branch 3 times, most recently from 991ba1a to e23de7a Compare August 26, 2014 15:04
@TomasVotruba
Copy link
Contributor

Almost 2 years passed... this is now solved by CompilerExtension, composer and bower.
Suggest closing.

@fprochazka
Copy link
Contributor

I don't like the proposed solution.

@JanJakes
Copy link
Author

@TomasVotruba I agree that this issue is already outdated but I would argue about that "this is now solved". Nette is still missing a complete, unified, and easy-to-use addon/package support even though compiler extensions are very powerful. However, I agree that this solution is not the right way. Something like http://forum.nette.org/en/18888-extending-extensions-solid-modular-concept is a much better way to go.

@fprochazka The funny thing is that the solution is from like 90% based on yours :) Although I was initially inspired by Symfony, the final solution came mostly from Kdyby at that time.

Anyway, you're right about closing this issue.

@JanJakes JanJakes closed this Aug 30, 2014
@TomasVotruba
Copy link
Contributor

@JanJakes Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants