joomla/joomla-cms — pull request #1419 by phproberto (2013-07-06 02:21:11+00:00)
Title: JLayoutFile improvements

This contribution tries to improve layouts usability for component developers without breaking B/C. New methods allow to:

* Allow devs to add an unlimited list of include paths with new functions: addIncludePath() & addIncludePaths
* Automatically search base layout overrides in the rendered component folder
* Automatically search overriden component layouts in the active template folder
* Add a sublayout function that inherits all the settings (except $layoutId & displayData from the parent folder)

## Old method

With the old method a simple call like this:

```PHP
$layout = new JLayoutFile('joomla.content.tags');
$layout->render($itemTags);
```
Will search for the layout in this folders (ordered by priority):
```
[0] => templates/mytemplate/html/layouts
[1] => layouts
```

You also could force a layout folder with:

```PHP
$layout = new JLayoutFile('joomla.content.tags', JPATH_SITE . '/components/com_mycomponent/layouts');
$layout->render($itemTags);
```
Which would search for layouts in:
```
[0] => templates/mytemplate/html/layouts
[1] => components/com_mycomponent/layouts
```

That limits layout search to two folders and doesn't allow users to create layout overrides per component.

## New method

Standard call (with default values shown) would be like:

```PHP
JLayoutFile($layoutId, $basePath = null, $component = 'auto', $client = 'auto', $debug = false)
```
No B/C issues. Now let's use some examples to describe new features:

### 1. I want to customise the way that tags are shown in my component.

With the new functions you haven't to do anything. System will automatically search for layouts in the active component:

```PHP
$layout = new JLayoutFile('joomla.content.tags');
$layout->render($itemTags);
```
Will search for layouts in this order:
```
[0] => templates/mytemplate/html/layouts/com_mycomponent
[1] => components/com_mycomponent/layouts
[2] => templates/mytemplate/html/layouts
[3] => layouts
```
That means that I can customise tags and also users can specifically override my customisation.

### 2. Wait I'm in a module that shows my component tags in any component

You can specify/force the component where you want to search for layouts

```PHP
$layout = new JLayoutFile('joomla.content.tags', null, 'com_mycomponent');
$layout->render($itemTags);
```

### 3. But I want to show my tags in backend with the same frontend layout

You can also specify the client where you want to search for layouts:

```PHP
$layout = new JLayoutFile('joomla.content.tags', null, 'com_mycomponent', 'site');
$layout->render($itemTags);
```

### 4. Why sublayouts?
I found that I needed to always use the same includePaths to render a lot of layouts. Let's say that we are on a plugin that creates an invoice. With sublayouts it's easy to allow users to customise exactly the part of the invoice the want. In the main file we will call something like:

```PHP
$invoiceLayout = new JLayoutFile('invoice', null, 'com_mycomponent', 'site');
$invoiceLayout->render($invoiceData);
```

And then in the layout we can use:
```PHP
// Render client information
echo $this->sublayout('invoice.client', $client);

// Render products lines
echo $this->sublayout('invoice.products', $products);
```

That will create a group of small layouts that clients can customise individually. For example to customise client information they just need to copy the file from:

components/com_mycomponent/layouts/invoice/client.php

to the template:

templates/mytemplate/html/layouts/com_mycomponent/invoice/client.php

### 5. Debug mode

As you may have noticed all this folders in the include path can cause you some headaches when any of them fails. When enabled debug mode will output something like this when the render() method is called:
![layouts_debug](https://f.cloud.github.com/assets/1119272/756072/d6d740a8-e5df-11e2-8c02-610e0beeb6c9.png)

You can also use echo $layout->debugInfo(); anytime.

### 6. Playground

I also added some new public available functions:

```
setComponent($component)
setClient($client)
setLayout($layoutId)
setDebug($debug)
```

They are mainly intended to be used internall but nothing prevents you to go crazy and do something like:

```PHP
$layout = new JLayoutFile('invoice', null, 'com_mycomponent', 'site');
echo $layout->render($invoiceData);

// Crazy mode
$layout->setLayout('share');
$layout->setComponent('com_weblinks');
$layout->setClient('admin');
echo $layout->render($links);
```

### 7. Also available in fast layout mode

If you like to save lines of code you can use the JLayoutHelper which also includes the new features:

```PHP
public static function render($layoutFile, $displayData = null, $basePath = '', $component = 'auto', $client = 'auto', $debug = false)
```

Some of the before examples in fast mode:

```PHP
echo JLayoutHelper::render('joomla.content.tags', $itemTags, null, 'com_mycomponent', 'site')
echo JLayoutHelper::render('invoice', $invoiceData, null, 'com_mycomponent', 'site');
```