? ? ? Failure

User tests: Successful: Unsuccessful:

avatar phproberto
phproberto
4 Mar 2014

Feature tracker: http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=33415

This also fixes this issue:
http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&tracker_item_id=33618

This pull request introduces some new JLayout based features:

JLayout improvements

1. Chainable methods

I have added the option to chain methods when possible. Now you can do:

$renderer = new JLayoutFile('joomla.content.tags', null, array('debug' => true));

echo $renderer
    ->setClient(0)
    ->setComponent('com_categories')
    ->render($this->item->tags->itemTags);

2. Suffixes improvements

Version 3.2 already supported suffixes but I created some improvements.

2.1 Add suffixes dynamically

Now suffixes can be added dynamically with setSuffixes($suffixes) method. Example:

$renderer = new JLayoutFile('joomla.content.tags', null, array('debug' => true));

echo $renderer
    ->setComponent('com_content')
    ->setClient(1)
    ->setSuffixes(array('j25'))
    ->render($this->item->tags->itemTags);

2.2 Automatic version suffixes

Most extended suffixes use was for having different versions for Joomla 2.5 & Joomla 3.x. I've added an automatic mode that will load the default version suffixes:

$renderer = new JLayoutFile('joomla.content.tags', null, array('debug' => true));

echo $renderer
    ->setSuffixes('autoversion')
    ->render($this->item->tags->itemTags);

Will automatically load this suffixes when executed on Joomla 3.2.3:

Suffixes: Array
(
    [0] => j323
    [1] => j32
    [2] => j3
)

So it will search for a layout in this priority order:

Searching layout for: joomla/content/tags.j323.php
Searching layout for: joomla/content/tags.j32.php
Searching layout for: joomla/content/tags.j3.php
Searching layout for: joomla/content/tags.php

This is mainly intended to be used on classes that extend JLayoutFile because sadly layouts are not available on Joomla 2.5.x series (they are included on FOF now).

For example an extended class running the same code on Joomla 2.5.18 will search layouts on:

Searching layout for: joomla/content/tags.j2518.php
Searching layout for: joomla/content/tags.j25.php
Searching layout for: joomla/content/tags.j2.php
Searching layout for: joomla/content/tags.php

As you can see is useful to have layout specific for a Joomla version.

2.3 Automatic language suffixes

This is an automatic suffix mode language oriented. Example:

$renderer = new JLayoutFile('joomla.content.tags', null, array('debug' => true));

echo $renderer
    ->setSuffixes('autolanguage')
    ->render($this->item->tags->itemTags);

It will automatically add this suffixes when executed on a site with en-GB language active.

Suffixes: Array
(
    [0] => en-GB
    [1] => en
    [2] => ltr
)

So you can create a layout for:

  • This specific locale
  • This specific language
  • This specific language direction

Good examples would be addresses that are ordered differently on different languages or layouts specifics to RTL (Right To Left) languages

3. Prefixes support

Now JLayoutFile also supports prefixes. This is mainly to group different prefixes under the same prefix. In the practice a prefix is a main folder that stores all that layouts. Example:

$renderer = new JLayoutFile('joomla.content.tags', null, array('debug' => true));

echo $renderer
    ->setPrefixes('bootstrap3')
    ->render($this->item->tags->itemTags);

It will search layouts in this order when called from the article view:

Include Paths: Array
(
    [0] => templates/protostar/html/layouts/com_content/bootstrap3
    [1] => components/com_content/layouts/bootstrap3
    [2] => templates/protostar/html/layouts/bootstrap3
    [3] => layouts/bootstrap3
    [4] => templates/protostar/html/layouts/com_content
    [5] => components/com_content/layouts
    [6] => templates/protostar/html/layouts
    [7] => layouts
)

So for example if you are on a template that supports both bootstrap2 & bootstrap3 mode you can put in the layouts/bootstrap3 folder the specific layouts for bootstrap3.

4. Cached file searches

When a layout is already searched in a specific list of include paths the final path is saved on cache. Next time the layout is searched in that list of include paths the cached path will be returned.

5. Statistics

Now JLayoutFile stores statistics about its use. To get the stats you have to use:

$stats = JLayoutFile::getStats();

It will return something like:

Array
(
    [fileSearches] => 20
    [fileSearchesCached] => 11
    [fileSearchesSkipped] => 0
    [times] => Array
        (
            [fileSearching] => 0.0028524398803711
            [fileRendering] => 0.024386882781982
            [/var/www/jcms3x/layouts/plugins/content/vote/vote.php] => 0.0019118785858154
            [/var/www/jcms3x/layouts/joomla/content/blog_style_default_item_title.php] => 0.0065479278564453
            [/var/www/jcms3x/layouts/joomla/content/icons.php] => 0.005518913269043
            [/var/www/jcms3x/layouts/joomla/content/info_block/author.php] => 0.00033211708068848
            [/var/www/jcms3x/layouts/joomla/content/info_block/category.php] => 0.0012009143829346
            [/var/www/jcms3x/layouts/joomla/content/info_block/publish_date.php] => 0.00086474418640137
            [/var/www/jcms3x/layouts/joomla/content/info_block/hits.php] => 0.0002598762512207
            [/var/www/jcms3x/layouts/joomla/content/info_block/block.php] => 0.0072002410888672
            [/var/www/jcms3x/layouts/joomla/content/intro_image.php] => 0.00026798248291016
        )

    [layoutsRendered] => Array
        (
            [/var/www/jcms3x/layouts/plugins/content/vote/vote.php] => 2
            [/var/www/jcms3x/layouts/joomla/content/blog_style_default_item_title.php] => 2
            [/var/www/jcms3x/layouts/joomla/content/icons.php] => 2
            [/var/www/jcms3x/layouts/joomla/content/info_block/block.php] => 4
            [/var/www/jcms3x/layouts/joomla/content/info_block/author.php] => 2
            [/var/www/jcms3x/layouts/joomla/content/info_block/category.php] => 2
            [/var/www/jcms3x/layouts/joomla/content/info_block/publish_date.php] => 2
            [/var/www/jcms3x/layouts/joomla/content/info_block/hits.php] => 2
            [/var/www/jcms3x/layouts/joomla/content/intro_image.php] => 2
        )

)

All the stats in a single array.

5.1 Stats details

$stats['fileSearches'] : Number of layout searches performed
$stats['fileSearchesCached'] : Number of layout searches returning cached paths
$stats['fileSearchesSkipped'] : Number of layout searches skipped because they share same instance with same params
$stats['times']: Array containing different times tracked
$stats['times']['fileSearching']: Total time spent searching layouts on file system
$stats['times']['fileRendering']: Total time spent rendering layouts
$stats['times'][$path]: System stores also time spent rendering each layout. This includes the global rendering time of rendering all appearences of this layout.
$stats['layoutsRendered']: Array containing the list of layouts rendered (array key) and the times it has been rendered ( value).

6. Better includepaths handling

In the previous versions you could not specify a list of include paths. The layout paths were always calculated automatically. Now you have total control over them

6.1 setIncludePaths

$renderer = new JLayoutFile('joomla.content.tags', null, array('debug' => true));

$renderer->setIncludePaths(
    array(
        JPATH_COMPONENT . '/layouts',
        JPATH_SITE . '/layouts'
    )
);

echo $renderer->render($this->item->tags->itemTags);

Will search for layouts on:

Include Paths: Array
(
    [0] => /var/www/jcms3x/components/com_content/layouts
    [1] => /var/www/jcms3x/layouts
)

6.1 resetIncludePaths

Delete the include paths information

echo $renderer
    ->setIncludePaths(
        array(
            JPATH_COMPONENT . '/layouts',
            JPATH_SITE . '/layouts'
        )
    )
    ->resetIncludePaths()
    ->addIncludePaths(
        array(
            JPATH_COMPONENT . '/layouts-new',
            JPATH_SITE . '/layouts-new'
        )
    )
    ->render($this->item->tags->itemTags);

will search in this include paths:

Include Paths: Array
(
    [0] => /var/www/jcms3x/components/com_content/layouts-new
    [1] => /var/www/jcms3x/layouts-new
)

6.2 loadDefaultIncludePaths

It will load the automatically calculated paths.

JFormField improvements

1. Field requirements support

This adds the option for fields to specify requirements that will prevent the field from being loaded.

There are only 2 main requirements defined at this point:

  • multilanguage : Requires language filter is enabled
  • associations : Requires language associations enabled

Note: This adds the support but most of the fields will require to modify the geInput() method to add the $this->validateRequirements() call. So don't expect it works on all fields out of the box. It should only work on labels and on text field.

A sample field definition:

<field 
    name="title" 
    type="text" 
    label="JGLOBAL_TITLE"
    description="JFIELD_TITLE_DESC"
    requires="multilanguage"
    required="true" 
/>

You can specify more than one requirement:

<field 
    name="title" 
    type="text" 
    label="JGLOBAL_TITLE"
    description="JFIELD_TITLE_DESC"
    requires="multilanguage,associations"
    required="true" 
/>

You can easily extend requirements for your field like:

/**
 * Function to determine if field validates the requirements
 *
 * @return  boolean
 */
protected function validateRequirements()
{
    if (parent::validateRequirements())
    {
        $requires = explode(',', (string) $this->element['requires']);

        if (in_array('myrequirement', $requires) && !MyHelper::validateRequirement())
        {
            return false;
        }
    }

    return true;
}

2. Layouts support

This adds support to use JLayoutFile to render form fields. This is added in JFormField but it doesn't change most of the existing fields to ensure BC. So don't expect it to work out of the box on all the fields. Included fields are:

  • JFormFieldList
  • JFormFieldUser

Now layouts can be defined inside fields setting the property $layout:

    /**
     * Layout to render
     *
     * @var  string
     */
    protected $layout = 'joomla.form.field.list';

But they also can be overriden on form. Thanks to this we can save to create new fields when the logic to get the data is the same and only the logic to render it changes. Examples would be to load select2 on a field for example:

<field
    name="show_title"
    type="list"
    class="chzn-color"
    label="JGLOBAL_SHOW_TITLE_LABEL"
    description="JGLOBAL_SHOW_TITLE_DESC"
    layout="joomla.form.field.select2"
    >
    <option value="">JGLOBAL_USE_GLOBAL</option>
    <option value="1">JSHOW</option>
    <option value="0">JHIDE</option>
</field>

Or imagine that you have a layout to render a filed loading typeahead.js field:

<field 
    name="title" 
    type="list" 
    label="JGLOBAL_TITLE"
    description="JFIELD_TITLE_DESC"
    layout="form.field.typeahead"
    required="true" 
/>

You can also set a specific layout for the label and layout prefixes/suffixes on your field class:

/**
 * Layout to render the field label
 *
 * @var  string
 */
protected $labelLayout = 'joomla.form.field.label';

/**
 * Prefixes to use to render the field.
 *
 * @var  array
 */
protected $layoutPrefixes = array();

/**
 * Suffixes to use to render the field.
 *
 * @var  array
 */
protected $layoutSuffixes = array();

or in your form XML file:

<field
    name="show_title"
    type="list"
    class="chzn-color"
    label="JGLOBAL_SHOW_TITLE_LABEL"
    description="JGLOBAL_SHOW_TITLE_DESC"
    label-layout="joomla.form.field.label2"
    layout-prefixes="bootstrap3"
    layout-suffixes="j25"
    >
    <option value="">JGLOBAL_USE_GLOBAL</option>
    <option value="1">JSHOW</option>
    <option value="0">JHIDE</option>
</field>

3. Overridable getRenderer

If you want to change the default paths or load your extended class instead of JLayoutFile you can nor override the getRenderer method:

/**
 * Get the layout used to render the field.
 *
 * @param   string  $layoutId  Layout to render
 * @param   mixed   $options   Optional custom options to load. JRegistry or array format
 *
 * @return  JLayoutFile  The layout
 */
public function getRenderer($layoutId, $options = array())
{
    $prefixes = !empty($this->element['layout-prefixes']) ? explode(',', $this->element['layout-prefixes']) : $this->layoutPrefixes;
    $suffixes = !empty($this->element['layout-suffixes']) ? explode(',', $this->element['layout-suffixes']) : $this->layoutSuffixes;

    $options = array_merge(array('prefixes' => $prefixes, 'suffixes' => $suffixes), $options);

    return new JLayoutFile($layoutId, null, $options);
}

This gives a very flexible tool to developers.

Plugins improvements

1. Layout support

Now in your plugin you can do something like:

return $this->getRenderer('default')->render(
    array(
        'context' => $context,
        'row'     => $row,
        'params'  => $params,
        'page'    => $page
    )
);

It will search a default.php layout on:

Include Paths: Array
(
    [0] => /var/www/jcms3x/templates/protostar/html/layouts/plugins/content/vote
    [1] => /var/www/jcms3x/layouts/plugins/content/vote
)

Note: All the plugins are still using the old hardcoded method. Only the plugin content/vote has been converted for testing purposes.

2. Layouts information on debug

Now the debug console shows all the information of the layouts loaded in the current page:

layouts-article-form

Testing

Required tests include:

  • Check that all list fields are shown and work correctly (including tags and all other extending fields)
  • Check that user field works correctly
  • Check that when you enable the option to show votes on articles it's dispalyed correctly
  • Make performance tests with & without this patch to ensure that layouts doesn't overload system.
  • Common layout override tests with prefixes, suffixes, include paths....

Votes

# of Users Experiencing Issue
2/2
Average Importance Score
5.00

avatar phproberto phproberto - open - 4 Mar 2014
avatar phproberto phproberto - change - 4 Mar 2014
Labels
avatar phproberto phproberto - change - 4 Mar 2014
Labels Added: ?
avatar wilsonge
wilsonge - comment - 4 Mar 2014

I owe you so so so many beers :D :D

avatar phproberto phproberto - change - 4 Mar 2014
Labels
avatar phproberto phproberto - change - 4 Mar 2014
Labels
avatar phproberto
phproberto - comment - 4 Mar 2014

I'll review travis errors tomorrow :dart:

avatar Bakual
Bakual - comment - 4 Mar 2014

I think you forgot to include the layout for the vote plugin? Vote doesn't show currently.

About the stats collecting. If I saw this correct you're doing that always? Wouldn't it make sense to only do that when debug is enabled? Otherwise we just generate overhead here for no reason.

About the prefix, I'm not sure I understand the intention here:

So for example if you are on a template that supports both bootstrap2 & bootstrap3 mode you can put in the layouts/bootstrap3 folder the specific layouts for bootstrap3.

As I understand it, the prefix (as well as suffixes, autolanguage and others) is set by the extension. How does that help a template? Or is that something a template could set globally?
Developers likely only add those if they provide different layouts themself. So most will not enable that. After all it's also a bit of a performance issue to look up ~15 override paths per layout (3 from autolanguage, 3 from autoversion, 7 from prefix plus the regular ones).
Writing this, I just wonder what exactly happens when we have both prefixes and suffixes set. Do they multiplicate? Then that would make the above ~42 (7 prefix * 6 suffix) include paths to look up... That's makes be a bit feared right now.

Generally speaking, while I like what you did here, I fear this PR got a bit big which makes it harder to test. Especially since there are so many places one would have to test things. If you could for example split it up into a part for the basic enhancement (maybe with the plugin) and another for the JForm part, that would help. If the JForm one does depend on the basic one, it may be better to do it incrementally.

avatar phproberto phproberto - change - 4 Mar 2014
Title
[imp] layout improvements and base system for fields
[#33415] [imp] layout improvements and base system for fields
avatar phproberto phproberto - change - 4 Mar 2014
Status New Closed
Closed_Date 0000-00-00 00:00:00 2014-03-04 09:50:52
avatar phproberto phproberto - close - 4 Mar 2014
avatar phproberto phproberto - close - 4 Mar 2014
avatar phproberto phproberto - head_ref_deleted - 4 Mar 2014
avatar wilsonge
wilsonge - comment - 4 Mar 2014

Would we be able to integrate into the JForm class a method to add a prefix/suffix to the layouts for all form fields? So if I want to say load bootstrap 2/3 classes or even frameworky. I can load that for all fields in the form instead of having to override the layout path for each individual field?

Just to be an arse :D

avatar phproberto
phproberto - comment - 4 Mar 2014

Sorry I forgot to answer before closing the PR. Thanks for checking it.

@Bakual :

I think you forgot to include the layout for the vote plugin? Vote doesn't show currently.

Yes. I forgot the vote layout. Thanks for pointing it. I added it before closing this to be sure I have all ready here.

About the stats collecting. If I saw this correct you're doing that always? Wouldn't it make sense to only do that when debug is enabled? Otherwise we just generate overhead here for no reason.
about the

It's not a overhead to store 10 vars (counters) in an array. There is no performance issue for having it enabled it just increases counters and get microtimes. Maybe in the future if the system ges complex it will make sense. I invite you to waste your time doing performance tests.

About prefixes, suffixes: they are there for anybody that wants to use them. Of course you have to use the tools in a good way. That's the main reason to have now the layouts debug. The caching system will also help. I'll appreciate that the next time I propose something (with the tools to test it) you waste your time testing it before suggesting issues.

Generally speaking, while I like what you did here, I fear this PR got a bit big which makes it harder to test. Especially since there are so many places one would have to test things. If you could for example split it up into a part for the basic enhancement (maybe with the plugin) and another for the JForm part, that would help. If the JForm one does depend on the basic one, it may be better to do it incrementally.

This is something that needed to go together. The system was done to be a first step into the right direction and to start using the tools in the right way at the same time. 3.3 release was next week and you knew it.

I know it's not something easy to test. It wasn't to code and double check it. That's why I closed the PR. I'm not ready to rush during a week to explain why I use !empty() or discuss what should go inside a layout or not. Not prepared for a full week like that to get this merged. It's quite unmotivating to talk about the finger when it's pointing to a bigger thing.

I have lost a lot of sleeping time to get this done. I won't lose more.

@wilsonge I faced that problem but I'm not sure modifying JForm is a good move. Probably the best move here would be to search the way to allow form XML overriding. This will solve this and many other issues.

avatar phproberto phproberto - head_ref_restored - 4 Mar 2014
avatar phproberto phproberto - change - 4 Mar 2014
Status Closed New
avatar phproberto phproberto - reopen - 4 Mar 2014
avatar phproberto phproberto - reopen - 4 Mar 2014
avatar Bakual
Bakual - comment - 4 Mar 2014

@phproberto I certainly didn't want to demotivate you and I am sorry if it came across like this.
It's hard to test something when you don't know the ins and outs of the code involved.
To test this I probably have to invest a whole evening. I'm happy to do that because I think it's a good move. But I would like to understand it prior to testing. That's why I asked the questions based on looking at your description (and briefly code) to get it right.

avatar phproberto
phproberto - comment - 4 Mar 2014

I've sent a new commit to add layout support for views. It's intended to replace the old system (template folders are the same). So we cannot use it on core components for now because BC but we can start using it for new views and start encouraging extension developers to use it.

To switch to the new system you have to replace in your view display method:

parent::display($tpl);

with:

echo  $this->getRenderer('default')->render(
    array(
        'items'      => $this->items,
        'pagination' => $this->pagination,
        'state'      => $this->state,
        'user'       => $this->user
    )
);
avatar phproberto
phproberto - comment - 4 Mar 2014

I removed the new mvc view path. For classes that use the view folder they can override the getRenderer method.

Branch rebased

avatar wilsonge
wilsonge - comment - 4 Mar 2014

OK awesome :) I've been really busy today but I'll have this tested tomorrow (afternoon/evening) :D

avatar phproberto
phproberto - comment - 6 Mar 2014

Review all extended JFormFieldList fields

To fully ensure BC I will review that all the fields that extend JFormFieldList work.

  • Bannerclient
  • CategoryEdit
  • CategoryParent
  • Directories
  • SearchFilter
  • MenuOrdering
  • MenuParent
  • Menutype
  • Newsfeeds
  • GroupParent
  • Language
  • Author
  • Contentlanguage
  • Contenttype
  • Headertag
  • Helpsite
  • Limitbox
  • Menu
  • Moduletag
  • Tag
  • UserGroupList
  • AccessLevel
  • CacheHandler
  • Combo
  • DatabaseConnection
  • FileList
  • FolderList
  • Integer
  • Language
  • Plugins
  • PredefinedList
  • SessionHandler
  • SQL
  • Category
avatar phproberto
phproberto - comment - 6 Mar 2014

I converted getRenderer view method to public to be able to render a view inside another view (pseudo-HMVC) :dancer:

avatar wilsonge
wilsonge - comment - 6 Mar 2014

:+1:

avatar phproberto
phproberto - comment - 7 Mar 2014

Rebased vs latest staging to resolve conflicts

avatar wilsonge
wilsonge - comment - 10 Mar 2014

Roberto - somethings weird. I can't seem to use pagination in the article manager (it works in a clean 3.2.3 install so not sure what the hell is going on) - I don't understand at all why your changes would affect that specific pagination though :/

avatar wilsonge
wilsonge - comment - 10 Mar 2014

Further to the above it also appears in banners (and is related to the search tools - as these are the two components where search tools appears to be used) - it would appear that everytime to press anything in pagination for some reason unpublish is being selected in the search tools - even when it's not open - god knows why

avatar phproberto
phproberto - comment - 12 Mar 2014

Thanks for testing @wilsonge

The problem with pagination was that it was identifying "" as 0. That's why unpublished was always selected

avatar wilsonge
wilsonge - comment - 12 Mar 2014

Ahh I see. I've just hit a PR into your branch that starts to deal with the unit test failures. Not sure how you want to deal with the layout changes - whether in the JLayout or in the unit tests themselves. Updates look good on a quick run through in localhost but will test more thoroughly tomorrow as pretty tired right now :)

avatar phproberto
phproberto - comment - 12 Mar 2014

I'm not sure neither but maybe in the unit tests is better no? To compare field properties

avatar wilsonge
wilsonge - comment - 12 Mar 2014

Hmm probably. Not quite sure how we'd go about comparing the properties though other than doing some nasty preg_replace checks or something like that :/ Will have a ponder. At least the unit test failures now are just due to the spacings in the fields

In the meantime I've found an absolutely critical bug. See my PR :P

avatar wilsonge
wilsonge - comment - 12 Mar 2014

@mbabker Any preferences on how to deal with the unit test changes which are failing cause of the extra line breaks?

avatar wilsonge
wilsonge - comment - 13 Mar 2014

OK :) Looks perfect to me!

avatar phproberto
phproberto - comment - 13 Mar 2014

To get this on 3.3 we have to fix the unit tests and get this tested by more people in next 1-2 days

avatar wilsonge
wilsonge - comment - 13 Mar 2014

I can do the tests. There's already 1 other test on the tracker and I can hopefully get 1 more to test. 3 testers + passing tests should be enough to set ready for review

avatar fhouenou
fhouenou - comment - 13 Mar 2014

Test done successfully.

avatar phproberto
phproberto - comment - 13 Mar 2014

Rebased again

avatar rdeutz
rdeutz - comment - 13 Mar 2014

Tested the suffix thing, struggled a bit about the setSuffixes('autoversion') and setSuffixes('auto language'), because one overwrites the other, I had expected that using both results in something like:

file.en.j3.php
file.lrt.j3.php

....

It's complicated but maybe worth thinking about, maybe for one of the next version something like "autoall".

avatar phproberto
phproberto - comment - 13 Mar 2014

Thanks Robert!

I thought about mixing both but that would be 4 x 3 = 12 file searches. I agree it can be a good thing in next versions but for now I'd ensure that the system is stable with current changes and incoming layout conversions.

avatar wilsonge
wilsonge - comment - 15 Mar 2014

PR to fix the tests is awaiting you :)

avatar b2z
b2z - comment - 21 Mar 2014

@phproberto great job as always :) I've noticed that you've added a renderData method. May be it is logical to change render to renderData in the helper?

avatar phproberto
phproberto - comment - 26 Mar 2014

mmm sorry @b2z I forgot to comment that feature :D

The renderData is intended to be the final rendering method (programmaticaly talking). It adds some feature commonly used on other rendering systems:

Assign variables while you create them

$renderer = new JLayoutFile('joomla.content.tags', null, array('debug' => true));

$calculatedVar = 105 / 5;

$renderer->assign('myVar', $calculatedVar);

echo $renderer->renderData(array('anotherVar', 145));

The main problem with this is that it expects that you always pass an array to the renderer and that's not BC because we now have places were we are passing view instances directly for example.

That's why I had to create a new method.

The helper is intended to be a fast call to load a layout and render it with the given data. So you can still use the old call. I think we can standarize the calls for 4.0 but not before.

I'll add this documentation to the PR text. Thanks for pointing it.

P.S.: I rebased it and fixed some conflicts with current master

avatar b2z
b2z - comment - 26 Mar 2014

@phproberto thanks, now it is clear!

avatar mbabker
mbabker - comment - 31 Mar 2014

So, for the tests, I think if they were rewritten using PHPUnit's internal tag checker (like was done at 8165137) then the failures would probably go away and we wouldn't have to rewrite them just because the way the fields are rendered is changed.

avatar zero-24
zero-24 - comment - 18 Apr 2014

@phproberto
After applying the patch (setup: 3.3beta2, this patch with com_patchtester) get this error:
Fatal error: Cannot redeclare JFormField::validateRequirements() in /www/htdocs/custompath/libraries/joomla/form/field.php on line 1005
E.g. by accessing the menu item edit page at the Backend:
http://www.example.org/administrator/index.php?option=com_menus&view=items&menutype=usermenu
Or Mass Mail Users view:
http://www.example.org/administrator/index.php?option=com_users&view=mail

After turn this into a comment line The views will work.
https://github.com/phproberto/joomla-cms/blob/layouts-field/libraries/joomla/form/field.php#L1000-1024

avatar zero-24
zero-24 - comment - 18 Apr 2014

@phproberto tests the debug feature is ok. Looks very good here, like it :+1:
Also User field look good here. (Tested at the com_content article view at the created_by option)
Also tested some backend views with some fields. I have not see that any one failed.
Good work here :+1:

avatar phproberto phproberto - change - 29 May 2014
Description <p>Feature tracker: <a href="http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&amp;tracker_item_id=33415">http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&amp;tracker_item_id=33415</a></p> <p>This also fixes this issue:<br><a href="http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&amp;tracker_item_id=33618">http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&amp;tracker_item_id=33618</a></p> <p>This pull request introduces some new <code>JLayout</code> based features:</p> <h1>JLayout improvements</h1> <h2>1. Chainable methods</h2> <p>I have added the option to chain methods when possible. Now you can do:</p> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setClient</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">setComponent</span><span class="p">(</span><span class="s1">'com_categories'</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <h2>2. Suffixes improvements</h2> <p>Version 3.2 already supported suffixes but I created some improvements.</p> <h3>2.1 Add suffixes dynamically</h3> <p>Now suffixes can be added dynamically with <code>setSuffixes($suffixes)</code> method. Example:</p> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setComponent</span><span class="p">(</span><span class="s1">'com_content'</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">setClient</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">setSuffixes</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'j25'</span><span class="p">))</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <h3>2.2 Automatic version suffixes</h3> <p>Most extended suffixes use was for having different versions for Joomla 2.5 &amp; Joomla 3.x. I've added an automatic mode that will load the default version suffixes:</p> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setSuffixes</span><span class="p">(</span><span class="s1">'autoversion'</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <p>Will automatically load this suffixes when executed on Joomla 3.2.3:</p> <div class="highlight highlight-php"><pre><span class="nx">Suffixes</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">j323</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">j32</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">j3</span> <span class="p">)</span> </pre></div> <p>So it will search for a layout in this priority order:</p> <pre><code>Searching layout for: joomla/content/tags.j323.php Searching layout for: joomla/content/tags.j32.php Searching layout for: joomla/content/tags.j3.php Searching layout for: joomla/content/tags.php </code></pre> <p>This is mainly intended to be used on classes that extend <code>JLayoutFile</code> because sadly layouts are not available on Joomla 2.5.x series (they are included on FOF now). </p> <p>For example an extended class running the same code on Joomla 2.5.18 will search layouts on:</p> <pre><code>Searching layout for: joomla/content/tags.j2518.php Searching layout for: joomla/content/tags.j25.php Searching layout for: joomla/content/tags.j2.php Searching layout for: joomla/content/tags.php </code></pre> <p>As you can see is useful to have layout specific for a Joomla version.</p> <h3>2.3 Automatic language suffixes</h3> <p>This is an automatic suffix mode language oriented. Example:</p> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setSuffixes</span><span class="p">(</span><span class="s1">'autolanguage'</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <p>It will automatically add this suffixes when executed on a site with <code>en-GB</code> language active.</p> <div class="highlight highlight-php"><pre><span class="nx">Suffixes</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">en</span><span class="o">-</span><span class="nx">GB</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">en</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">ltr</span> <span class="p">)</span> </pre></div> <p>So you can create a layout for:</p> <ul> <li>This specific locale</li> <li>This specific language</li> <li>This specific language direction</li> </ul><p>Good examples would be addresses that are ordered differently on different languages or layouts specifics to <code>RTL</code> (Right To Left) languages</p> <h2>3. Prefixes support</h2> <p>Now <code>JLayoutFile</code> also supports prefixes. This is mainly to group different prefixes under the same prefix. In the practice a prefix is a main folder that stores all that layouts. Example:</p> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setPrefixes</span><span class="p">(</span><span class="s1">'bootstrap3'</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <p>It will search layouts in this order when called from the article view:</p> <div class="highlight highlight-php"><pre><span class="k">Include</span> <span class="nx">Paths</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">templates</span><span class="o">/</span><span class="nx">protostar</span><span class="o">/</span><span class="nx">html</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">com_content</span><span class="o">/</span><span class="nx">bootstrap3</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">components</span><span class="o">/</span><span class="nx">com_content</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">bootstrap3</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">templates</span><span class="o">/</span><span class="nx">protostar</span><span class="o">/</span><span class="nx">html</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">bootstrap3</span> <span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">layouts</span><span class="o">/</span><span class="nx">bootstrap3</span> <span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">templates</span><span class="o">/</span><span class="nx">protostar</span><span class="o">/</span><span class="nx">html</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">com_content</span> <span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">components</span><span class="o">/</span><span class="nx">com_content</span><span class="o">/</span><span class="nx">layouts</span> <span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">templates</span><span class="o">/</span><span class="nx">protostar</span><span class="o">/</span><span class="nx">html</span><span class="o">/</span><span class="nx">layouts</span> <span class="p">[</span><span class="mi">7</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">layouts</span> <span class="p">)</span> </pre></div> <p>So for example if you are on a template that supports both bootstrap2 &amp; bootstrap3 mode you can put in the layouts/bootstrap3 folder the specific layouts for bootstrap3. </p> <h2>4. Cached file searches</h2> <p>When a layout is already searched in a specific list of include paths the final path is saved on cache. Next time the layout is searched in that list of include paths the cached path will be returned.</p> <h2>5. Statistics</h2> <p>Now <code>JLayoutFile</code> stores statistics about its use. To get the stats you have to use:</p> <div class="highlight highlight-php"><pre><span class="nv">$stats</span> <span class="o">=</span> <span class="nx">JLayoutFile</span><span class="o">::</span><span class="na">getStats</span><span class="p">();</span> </pre></div> <p>It will return something like:</p> <div class="highlight highlight-php"><pre><span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="nx">fileSearches</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">20</span> <span class="p">[</span><span class="nx">fileSearchesCached</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">11</span> <span class="p">[</span><span class="nx">fileSearchesSkipped</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">0</span> <span class="p">[</span><span class="nx">times</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="nx">fileSearching</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0028524398803711</span> <span class="p">[</span><span class="nx">fileRendering</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.024386882781982</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">plugins</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">vote</span><span class="o">/</span><span class="nx">vote</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0019118785858154</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">blog_style_default_item_title</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0065479278564453</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">icons</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.005518913269043</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">author</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.00033211708068848</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">category</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0012009143829346</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">publish_date</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.00086474418640137</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">hits</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0002598762512207</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">block</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0072002410888672</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">intro_image</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.00026798248291016</span> <span class="p">)</span> <span class="p">[</span><span class="nx">layoutsRendered</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">plugins</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">vote</span><span class="o">/</span><span class="nx">vote</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">blog_style_default_item_title</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">icons</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">block</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">4</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">author</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">category</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">publish_date</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">hits</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">intro_image</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">)</span> <span class="p">)</span> </pre></div> <p>All the stats in a single array. </p> <h3>5.1 Stats details</h3> <p><code>$stats['fileSearches']</code> : Number of layout searches performed<br><code>$stats['fileSearchesCached']</code> : Number of layout searches returning cached paths<br><code>$stats['fileSearchesSkipped']</code> : Number of layout searches skipped because they share same instance with same params<br><code>$stats['times']</code>: Array containing different times tracked<br><code>$stats['times']['fileSearching']</code>: Total time spent searching layouts on file system<br><code>$stats['times']['fileRendering']</code>: Total time spent rendering layouts<br><code>$stats['times'][$path]</code>: System stores also time spent rendering each layout. This includes the global rendering time of rendering all appearences of this layout.<br><code>$stats['layoutsRendered']</code>: Array containing the list of layouts rendered (array key) and the times it has been rendered ( value). </p> <h2>6. Better includepaths handling</h2> <p>In the previous versions you could not specify a list of include paths. The layout paths were always calculated automatically. Now you have total control over them</p> <h3>6.1 setIncludePaths</h3> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="nv">$renderer</span><span class="o">-&gt;</span><span class="na">setIncludePaths</span><span class="p">(</span> <span class="k">array</span><span class="p">(</span> <span class="nx">JPATH_COMPONENT</span> <span class="o">.</span> <span class="s1">'/layouts'</span><span class="p">,</span> <span class="nx">JPATH_SITE</span> <span class="o">.</span> <span class="s1">'/layouts'</span> <span class="p">)</span> <span class="p">);</span> <span class="k">echo</span> <span class="nv">$renderer</span><span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <p>Will search for layouts on:</p> <div class="highlight highlight-php"><pre><span class="k">Include</span> <span class="nx">Paths</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">components</span><span class="o">/</span><span class="nx">com_content</span><span class="o">/</span><span class="nx">layouts</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span> <span class="p">)</span> </pre></div> <h3>6.1 resetIncludePaths</h3> <p>Delete the include paths information</p> <div class="highlight highlight-php"><pre><span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setIncludePaths</span><span class="p">(</span> <span class="k">array</span><span class="p">(</span> <span class="nx">JPATH_COMPONENT</span> <span class="o">.</span> <span class="s1">'/layouts'</span><span class="p">,</span> <span class="nx">JPATH_SITE</span> <span class="o">.</span> <span class="s1">'/layouts'</span> <span class="p">)</span> <span class="p">)</span> <span class="o">-&gt;</span><span class="na">resetIncludePaths</span><span class="p">()</span> <span class="o">-&gt;</span><span class="na">addIncludePaths</span><span class="p">(</span> <span class="k">array</span><span class="p">(</span> <span class="nx">JPATH_COMPONENT</span> <span class="o">.</span> <span class="s1">'/layouts-new'</span><span class="p">,</span> <span class="nx">JPATH_SITE</span> <span class="o">.</span> <span class="s1">'/layouts-new'</span> <span class="p">)</span> <span class="p">)</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <p>will search in this include paths:</p> <div class="highlight highlight-php"><pre><span class="k">Include</span> <span class="nx">Paths</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">components</span><span class="o">/</span><span class="nx">com_content</span><span class="o">/</span><span class="nx">layouts</span><span class="o">-</span><span class="k">new</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">-</span><span class="k">new</span> <span class="p">)</span> </pre></div> <h3>6.2 loadDefaultIncludePaths</h3> <p>It will load the automatically calculated paths.</p> <h1>JFormField improvements</h1> <h2>1. Field requirements support</h2> <p>This adds the option for fields to specify requirements that will prevent the field from being loaded. </p> <p>There are only 2 main requirements defined at this point:</p> <ul> <li> <strong>multilanguage</strong> : Requires language filter is enabled</li> <li> <strong>associations</strong> : Requires language associations enabled</li> </ul><p><strong>Note:</strong> This adds the support but most of the fields will require to modify the geInput() method to add the <code>$this-&gt;validateRequirements()</code> call. So don't expect it works on all fields out of the box. It should only work on labels and on text field.</p> <p>A sample field definition:</p> <div class="highlight highlight-xml"><pre><span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"title"</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">label=</span><span class="s">"JGLOBAL_TITLE"</span> <span class="na">description=</span><span class="s">"JFIELD_TITLE_DESC"</span> <span class="na">requires=</span><span class="s">"multilanguage"</span> <span class="na">required=</span><span class="s">"true"</span> <span class="nt">/&gt;</span> </pre></div> <p>You can specify more than one requirement:</p> <div class="highlight highlight-xml"><pre><span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"title"</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">label=</span><span class="s">"JGLOBAL_TITLE"</span> <span class="na">description=</span><span class="s">"JFIELD_TITLE_DESC"</span> <span class="na">requires=</span><span class="s">"multilanguage,associations"</span> <span class="na">required=</span><span class="s">"true"</span> <span class="nt">/&gt;</span> </pre></div> <p>You can easily extend requirements for your field like:</p> <div class="highlight highlight-php"><pre><span class="sd">/**</span> <span class="sd"> * Function to determine if field validates the requirements</span> <span class="sd"> *</span> <span class="sd"> * @return boolean</span> <span class="sd"> */</span> <span class="k">protected</span> <span class="k">function</span> <span class="nf">validateRequirements</span><span class="p">()</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="k">parent</span><span class="o">::</span><span class="na">validateRequirements</span><span class="p">())</span> <span class="p">{</span> <span class="nv">$requires</span> <span class="o">=</span> <span class="nb">explode</span><span class="p">(</span><span class="s1">','</span><span class="p">,</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">element</span><span class="p">[</span><span class="s1">'requires'</span><span class="p">]);</span> <span class="k">if</span> <span class="p">(</span><span class="nb">in_array</span><span class="p">(</span><span class="s1">'myrequirement'</span><span class="p">,</span> <span class="nv">$requires</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">MyHelper</span><span class="o">::</span><span class="na">validateRequirement</span><span class="p">())</span> <span class="p">{</span> <span class="k">return</span> <span class="k">false</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> <span class="k">return</span> <span class="k">true</span><span class="p">;</span> <span class="p">}</span> </pre></div> <h2>2. Layouts support</h2> <p>This adds support to use <code>JLayoutFile</code> to render form fields. This is added in <code>JFormField</code> but it doesn't change most of the existing fields to ensure BC. So don't expect it to work out of the box on all the fields. Included fields are:</p> <ul> <li>JFormFieldList</li> <li>JFormFieldUser </li> </ul><p>Now layouts can be defined inside fields setting the property <code>$layout</code>:</p> <div class="highlight highlight-php"><pre> <span class="sd">/**</span> <span class="sd"> * Layout to render</span> <span class="sd"> *</span> <span class="sd"> * @var string</span> <span class="sd"> */</span> <span class="k">protected</span> <span class="nv">$layout</span> <span class="o">=</span> <span class="s1">'joomla.form.field.list'</span><span class="p">;</span> </pre></div> <p>But they also can be overriden on form. Thanks to this we can save to create new fields when the logic to get the data is the same and only the logic to render it changes. Examples would be to load <code>select2</code> on a field for example:</p> <div class="highlight highlight-xml"><pre><span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"show_title"</span> <span class="na">type=</span><span class="s">"list"</span> <span class="na">class=</span><span class="s">"chzn-color"</span> <span class="na">label=</span><span class="s">"JGLOBAL_SHOW_TITLE_LABEL"</span> <span class="na">description=</span><span class="s">"JGLOBAL_SHOW_TITLE_DESC"</span> <span class="na">layout=</span><span class="s">"joomla.form.field.select2"</span> <span class="nt">&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">""</span><span class="nt">&gt;</span>JGLOBAL_USE_GLOBAL<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">"1"</span><span class="nt">&gt;</span>JSHOW<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">"0"</span><span class="nt">&gt;</span>JHIDE<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;/field&gt;</span> </pre></div> <p>Or imagine that you have a layout to render a filed loading <code>typeahead.js</code> field:</p> <div class="highlight highlight-xml"><pre><span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"title"</span> <span class="na">type=</span><span class="s">"list"</span> <span class="na">label=</span><span class="s">"JGLOBAL_TITLE"</span> <span class="na">description=</span><span class="s">"JFIELD_TITLE_DESC"</span> <span class="na">layout=</span><span class="s">"form.field.typeahead"</span> <span class="na">required=</span><span class="s">"true"</span> <span class="nt">/&gt;</span> </pre></div> <p>You can also set a specific layout for the label and layout prefixes/suffixes on your field class:</p> <div class="highlight highlight-php"><pre><span class="sd">/**</span> <span class="sd"> * Layout to render the field label</span> <span class="sd"> *</span> <span class="sd"> * @var string</span> <span class="sd"> */</span> <span class="k">protected</span> <span class="nv">$labelLayout</span> <span class="o">=</span> <span class="s1">'joomla.form.field.label'</span><span class="p">;</span> <span class="sd">/**</span> <span class="sd"> * Prefixes to use to render the field.</span> <span class="sd"> *</span> <span class="sd"> * @var array</span> <span class="sd"> */</span> <span class="k">protected</span> <span class="nv">$layoutPrefixes</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span> <span class="sd">/**</span> <span class="sd"> * Suffixes to use to render the field.</span> <span class="sd"> *</span> <span class="sd"> * @var array</span> <span class="sd"> */</span> <span class="k">protected</span> <span class="nv">$layoutSuffixes</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span> </pre></div> <p>or in your form XML file:</p> <div class="highlight highlight-xml"><pre><span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"show_title"</span> <span class="na">type=</span><span class="s">"list"</span> <span class="na">class=</span><span class="s">"chzn-color"</span> <span class="na">label=</span><span class="s">"JGLOBAL_SHOW_TITLE_LABEL"</span> <span class="na">description=</span><span class="s">"JGLOBAL_SHOW_TITLE_DESC"</span> <span class="na">label-layout=</span><span class="s">"joomla.form.field.label2"</span> <span class="na">layout-prefixes=</span><span class="s">"bootstrap3"</span> <span class="na">layout-suffixes=</span><span class="s">"j25"</span> <span class="nt">&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">""</span><span class="nt">&gt;</span>JGLOBAL_USE_GLOBAL<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">"1"</span><span class="nt">&gt;</span>JSHOW<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">"0"</span><span class="nt">&gt;</span>JHIDE<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;/field&gt;</span> </pre></div> <h2>3. Overridable getRenderer</h2> <p>If you want to change the default paths or load your extended class instead of <code>JLayoutFile</code> you can nor override the getRenderer method:</p> <div class="highlight highlight-php"><pre><span class="sd">/**</span> <span class="sd"> * Get the layout used to render the field.</span> <span class="sd"> *</span> <span class="sd"> * @param string $layoutId Layout to render</span> <span class="sd"> * @param mixed $options Optional custom options to load. JRegistry or array format</span> <span class="sd"> *</span> <span class="sd"> * @return JLayoutFile The layout</span> <span class="sd"> */</span> <span class="k">public</span> <span class="k">function</span> <span class="nf">getRenderer</span><span class="p">(</span><span class="nv">$layoutId</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">array</span><span class="p">())</span> <span class="p">{</span> <span class="nv">$prefixes</span> <span class="o">=</span> <span class="o">!</span><span class="k">empty</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">element</span><span class="p">[</span><span class="s1">'layout-prefixes'</span><span class="p">])</span> <span class="o">?</span> <span class="nb">explode</span><span class="p">(</span><span class="s1">','</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">element</span><span class="p">[</span><span class="s1">'layout-prefixes'</span><span class="p">])</span> <span class="o">:</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">layoutPrefixes</span><span class="p">;</span> <span class="nv">$suffixes</span> <span class="o">=</span> <span class="o">!</span><span class="k">empty</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">element</span><span class="p">[</span><span class="s1">'layout-suffixes'</span><span class="p">])</span> <span class="o">?</span> <span class="nb">explode</span><span class="p">(</span><span class="s1">','</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">element</span><span class="p">[</span><span class="s1">'layout-suffixes'</span><span class="p">])</span> <span class="o">:</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">layoutSuffixes</span><span class="p">;</span> <span class="nv">$options</span> <span class="o">=</span> <span class="nb">array_merge</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'prefixes'</span> <span class="o">=&gt;</span> <span class="nv">$prefixes</span><span class="p">,</span> <span class="s1">'suffixes'</span> <span class="o">=&gt;</span> <span class="nv">$suffixes</span><span class="p">),</span> <span class="nv">$options</span><span class="p">);</span> <span class="k">return</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="nv">$layoutId</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span><span class="p">);</span> <span class="p">}</span> </pre></div> <p>This gives a very flexible tool to developers.</p> <h1>Plugins improvements</h1> <h2>1. Layout support</h2> <p>Now in your plugin you can do something like:</p> <div class="highlight highlight-php"><pre><span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">getRenderer</span><span class="p">(</span><span class="s1">'default'</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span> <span class="k">array</span><span class="p">(</span> <span class="s1">'context'</span> <span class="o">=&gt;</span> <span class="nv">$context</span><span class="p">,</span> <span class="s1">'row'</span> <span class="o">=&gt;</span> <span class="nv">$row</span><span class="p">,</span> <span class="s1">'params'</span> <span class="o">=&gt;</span> <span class="nv">$params</span><span class="p">,</span> <span class="s1">'page'</span> <span class="o">=&gt;</span> <span class="nv">$page</span> <span class="p">)</span> <span class="p">);</span> </pre></div> <p>It will search a <code>default.php</code> layout on:</p> <div class="highlight highlight-php"><pre><span class="k">Include</span> <span class="nx">Paths</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">templates</span><span class="o">/</span><span class="nx">protostar</span><span class="o">/</span><span class="nx">html</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">plugins</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">vote</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">plugins</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">vote</span> <span class="p">)</span> </pre></div> <p><strong>Note:</strong> All the plugins are still using the old hardcoded method. Only the plugin <code>content/vote</code> has been converted for testing purposes.</p> <h2>2. Layouts information on debug</h2> <p>Now the debug console shows all the information of the layouts loaded in the current page:</p> <p><a href="https://camo.githubusercontent.com/2856d4aebcf013eba68d5f4592eb07d2bba80f6a/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313131393237322f323331373633342f64356163363163342d613335312d313165332d383534622d6163616336386536353638612e706e67" target="_blank"><img src="https://camo.githubusercontent.com/2856d4aebcf013eba68d5f4592eb07d2bba80f6a/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313131393237322f323331373633342f64356163363163342d613335312d313165332d383534622d6163616336386536353638612e706e67" alt="layouts-article-form" data-canonical-src="https://f.cloud.github.com/assets/1119272/2317634/d5ac61c4-a351-11e3-854b-acac68e6568a.png" style="max-width:100%;"></a></p> <h1>Testing</h1> <p>Required tests include:</p> <ul> <li>Check that all list fields are shown and work correctly (including tags and all other extending fields)</li> <li>Check that user field works correctly</li> <li>Check that when you enable the option to show votes on articles it's dispalyed correctly</li> <li>Make performance tests with &amp; without this patch to ensure that layouts doesn't overload system.</li> <li>Common layout override tests with prefixes, suffixes, include paths....</li> </ul> <p>Feature tracker: <a href="http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&amp;tracker_item_id=33415">http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&amp;tracker_item_id=33415</a></p> <p>This also fixes this issue:<br><a href="http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&amp;tracker_item_id=33618">http://joomlacode.org/gf/project/joomla/tracker/?action=TrackerItemEdit&amp;tracker_item_id=33618</a></p> <p>This pull request introduces some new <code>JLayout</code> based features:</p> <h1>JLayout improvements</h1> <h2>1. Chainable methods</h2> <p>I have added the option to chain methods when possible. Now you can do:</p> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setClient</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">setComponent</span><span class="p">(</span><span class="s1">'com_categories'</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <h2>2. Suffixes improvements</h2> <p>Version 3.2 already supported suffixes but I created some improvements.</p> <h3>2.1 Add suffixes dynamically</h3> <p>Now suffixes can be added dynamically with <code>setSuffixes($suffixes)</code> method. Example:</p> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setComponent</span><span class="p">(</span><span class="s1">'com_content'</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">setClient</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">setSuffixes</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'j25'</span><span class="p">))</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <h3>2.2 Automatic version suffixes</h3> <p>Most extended suffixes use was for having different versions for Joomla 2.5 &amp; Joomla 3.x. I've added an automatic mode that will load the default version suffixes:</p> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setSuffixes</span><span class="p">(</span><span class="s1">'autoversion'</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <p>Will automatically load this suffixes when executed on Joomla 3.2.3:</p> <div class="highlight highlight-php"><pre><span class="nx">Suffixes</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">j323</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">j32</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">j3</span> <span class="p">)</span> </pre></div> <p>So it will search for a layout in this priority order:</p> <pre><code>Searching layout for: joomla/content/tags.j323.php Searching layout for: joomla/content/tags.j32.php Searching layout for: joomla/content/tags.j3.php Searching layout for: joomla/content/tags.php </code></pre> <p>This is mainly intended to be used on classes that extend <code>JLayoutFile</code> because sadly layouts are not available on Joomla 2.5.x series (they are included on FOF now). </p> <p>For example an extended class running the same code on Joomla 2.5.18 will search layouts on:</p> <pre><code>Searching layout for: joomla/content/tags.j2518.php Searching layout for: joomla/content/tags.j25.php Searching layout for: joomla/content/tags.j2.php Searching layout for: joomla/content/tags.php </code></pre> <p>As you can see is useful to have layout specific for a Joomla version.</p> <h3>2.3 Automatic language suffixes</h3> <p>This is an automatic suffix mode language oriented. Example:</p> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setSuffixes</span><span class="p">(</span><span class="s1">'autolanguage'</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <p>It will automatically add this suffixes when executed on a site with <code>en-GB</code> language active.</p> <div class="highlight highlight-php"><pre><span class="nx">Suffixes</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">en</span><span class="o">-</span><span class="nx">GB</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">en</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">ltr</span> <span class="p">)</span> </pre></div> <p>So you can create a layout for:</p> <ul class="task-list"> <li>This specific locale</li> <li>This specific language</li> <li>This specific language direction</li> </ul><p>Good examples would be addresses that are ordered differently on different languages or layouts specifics to <code>RTL</code> (Right To Left) languages</p> <h2>3. Prefixes support</h2> <p>Now <code>JLayoutFile</code> also supports prefixes. This is mainly to group different prefixes under the same prefix. In the practice a prefix is a main folder that stores all that layouts. Example:</p> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setPrefixes</span><span class="p">(</span><span class="s1">'bootstrap3'</span><span class="p">)</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <p>It will search layouts in this order when called from the article view:</p> <div class="highlight highlight-php"><pre><span class="k">Include</span> <span class="nx">Paths</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">templates</span><span class="o">/</span><span class="nx">protostar</span><span class="o">/</span><span class="nx">html</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">com_content</span><span class="o">/</span><span class="nx">bootstrap3</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">components</span><span class="o">/</span><span class="nx">com_content</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">bootstrap3</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">templates</span><span class="o">/</span><span class="nx">protostar</span><span class="o">/</span><span class="nx">html</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">bootstrap3</span> <span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">layouts</span><span class="o">/</span><span class="nx">bootstrap3</span> <span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">templates</span><span class="o">/</span><span class="nx">protostar</span><span class="o">/</span><span class="nx">html</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">com_content</span> <span class="p">[</span><span class="mi">5</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">components</span><span class="o">/</span><span class="nx">com_content</span><span class="o">/</span><span class="nx">layouts</span> <span class="p">[</span><span class="mi">6</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">templates</span><span class="o">/</span><span class="nx">protostar</span><span class="o">/</span><span class="nx">html</span><span class="o">/</span><span class="nx">layouts</span> <span class="p">[</span><span class="mi">7</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="nx">layouts</span> <span class="p">)</span> </pre></div> <p>So for example if you are on a template that supports both bootstrap2 &amp; bootstrap3 mode you can put in the layouts/bootstrap3 folder the specific layouts for bootstrap3. </p> <h2>4. Cached file searches</h2> <p>When a layout is already searched in a specific list of include paths the final path is saved on cache. Next time the layout is searched in that list of include paths the cached path will be returned.</p> <h2>5. Statistics</h2> <p>Now <code>JLayoutFile</code> stores statistics about its use. To get the stats you have to use:</p> <div class="highlight highlight-php"><pre><span class="nv">$stats</span> <span class="o">=</span> <span class="nx">JLayoutFile</span><span class="o">::</span><span class="na">getStats</span><span class="p">();</span> </pre></div> <p>It will return something like:</p> <div class="highlight highlight-php"><pre><span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="nx">fileSearches</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">20</span> <span class="p">[</span><span class="nx">fileSearchesCached</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">11</span> <span class="p">[</span><span class="nx">fileSearchesSkipped</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">0</span> <span class="p">[</span><span class="nx">times</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="nx">fileSearching</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0028524398803711</span> <span class="p">[</span><span class="nx">fileRendering</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.024386882781982</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">plugins</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">vote</span><span class="o">/</span><span class="nx">vote</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0019118785858154</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">blog_style_default_item_title</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0065479278564453</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">icons</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.005518913269043</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">author</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.00033211708068848</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">category</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0012009143829346</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">publish_date</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.00086474418640137</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">hits</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0002598762512207</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">block</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.0072002410888672</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">intro_image</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mf">0.00026798248291016</span> <span class="p">)</span> <span class="p">[</span><span class="nx">layoutsRendered</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">plugins</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">vote</span><span class="o">/</span><span class="nx">vote</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">blog_style_default_item_title</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">icons</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">block</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">4</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">author</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">category</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">publish_date</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">info_block</span><span class="o">/</span><span class="nx">hits</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">joomla</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">intro_image</span><span class="o">.</span><span class="nx">php</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="mi">2</span> <span class="p">)</span> <span class="p">)</span> </pre></div> <p>All the stats in a single array. </p> <h3>5.1 Stats details</h3> <p><code>$stats['fileSearches']</code> : Number of layout searches performed<br><code>$stats['fileSearchesCached']</code> : Number of layout searches returning cached paths<br><code>$stats['fileSearchesSkipped']</code> : Number of layout searches skipped because they share same instance with same params<br><code>$stats['times']</code>: Array containing different times tracked<br><code>$stats['times']['fileSearching']</code>: Total time spent searching layouts on file system<br><code>$stats['times']['fileRendering']</code>: Total time spent rendering layouts<br><code>$stats['times'][$path]</code>: System stores also time spent rendering each layout. This includes the global rendering time of rendering all appearences of this layout.<br><code>$stats['layoutsRendered']</code>: Array containing the list of layouts rendered (array key) and the times it has been rendered ( value). </p> <h2>6. Better includepaths handling</h2> <p>In the previous versions you could not specify a list of include paths. The layout paths were always calculated automatically. Now you have total control over them</p> <h3>6.1 setIncludePaths</h3> <div class="highlight highlight-php"><pre><span class="nv">$renderer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="s1">'joomla.content.tags'</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="k">array</span><span class="p">(</span><span class="s1">'debug'</span> <span class="o">=&gt;</span> <span class="k">true</span><span class="p">));</span> <span class="nv">$renderer</span><span class="o">-&gt;</span><span class="na">setIncludePaths</span><span class="p">(</span> <span class="k">array</span><span class="p">(</span> <span class="nx">JPATH_COMPONENT</span> <span class="o">.</span> <span class="s1">'/layouts'</span><span class="p">,</span> <span class="nx">JPATH_SITE</span> <span class="o">.</span> <span class="s1">'/layouts'</span> <span class="p">)</span> <span class="p">);</span> <span class="k">echo</span> <span class="nv">$renderer</span><span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <p>Will search for layouts on:</p> <div class="highlight highlight-php"><pre><span class="k">Include</span> <span class="nx">Paths</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">components</span><span class="o">/</span><span class="nx">com_content</span><span class="o">/</span><span class="nx">layouts</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span> <span class="p">)</span> </pre></div> <h3>6.1 resetIncludePaths</h3> <p>Delete the include paths information</p> <div class="highlight highlight-php"><pre><span class="k">echo</span> <span class="nv">$renderer</span> <span class="o">-&gt;</span><span class="na">setIncludePaths</span><span class="p">(</span> <span class="k">array</span><span class="p">(</span> <span class="nx">JPATH_COMPONENT</span> <span class="o">.</span> <span class="s1">'/layouts'</span><span class="p">,</span> <span class="nx">JPATH_SITE</span> <span class="o">.</span> <span class="s1">'/layouts'</span> <span class="p">)</span> <span class="p">)</span> <span class="o">-&gt;</span><span class="na">resetIncludePaths</span><span class="p">()</span> <span class="o">-&gt;</span><span class="na">addIncludePaths</span><span class="p">(</span> <span class="k">array</span><span class="p">(</span> <span class="nx">JPATH_COMPONENT</span> <span class="o">.</span> <span class="s1">'/layouts-new'</span><span class="p">,</span> <span class="nx">JPATH_SITE</span> <span class="o">.</span> <span class="s1">'/layouts-new'</span> <span class="p">)</span> <span class="p">)</span> <span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">item</span><span class="o">-&gt;</span><span class="na">tags</span><span class="o">-&gt;</span><span class="na">itemTags</span><span class="p">);</span> </pre></div> <p>will search in this include paths:</p> <div class="highlight highlight-php"><pre><span class="k">Include</span> <span class="nx">Paths</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">components</span><span class="o">/</span><span class="nx">com_content</span><span class="o">/</span><span class="nx">layouts</span><span class="o">-</span><span class="k">new</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">-</span><span class="k">new</span> <span class="p">)</span> </pre></div> <h3>6.2 loadDefaultIncludePaths</h3> <p>It will load the automatically calculated paths.</p> <h1>JFormField improvements</h1> <h2>1. Field requirements support</h2> <p>This adds the option for fields to specify requirements that will prevent the field from being loaded. </p> <p>There are only 2 main requirements defined at this point:</p> <ul class="task-list"> <li> <strong>multilanguage</strong> : Requires language filter is enabled</li> <li> <strong>associations</strong> : Requires language associations enabled</li> </ul><p><strong>Note:</strong> This adds the support but most of the fields will require to modify the geInput() method to add the <code>$this-&gt;validateRequirements()</code> call. So don't expect it works on all fields out of the box. It should only work on labels and on text field.</p> <p>A sample field definition:</p> <div class="highlight highlight-xml"><pre><span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"title"</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">label=</span><span class="s">"JGLOBAL_TITLE"</span> <span class="na">description=</span><span class="s">"JFIELD_TITLE_DESC"</span> <span class="na">requires=</span><span class="s">"multilanguage"</span> <span class="na">required=</span><span class="s">"true"</span> <span class="nt">/&gt;</span> </pre></div> <p>You can specify more than one requirement:</p> <div class="highlight highlight-xml"><pre><span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"title"</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">label=</span><span class="s">"JGLOBAL_TITLE"</span> <span class="na">description=</span><span class="s">"JFIELD_TITLE_DESC"</span> <span class="na">requires=</span><span class="s">"multilanguage,associations"</span> <span class="na">required=</span><span class="s">"true"</span> <span class="nt">/&gt;</span> </pre></div> <p>You can easily extend requirements for your field like:</p> <div class="highlight highlight-php"><pre><span class="sd">/**</span> <span class="sd"> * Function to determine if field validates the requirements</span> <span class="sd"> *</span> <span class="sd"> * @return boolean</span> <span class="sd"> */</span> <span class="k">protected</span> <span class="k">function</span> <span class="nf">validateRequirements</span><span class="p">()</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="k">parent</span><span class="o">::</span><span class="na">validateRequirements</span><span class="p">())</span> <span class="p">{</span> <span class="nv">$requires</span> <span class="o">=</span> <span class="nb">explode</span><span class="p">(</span><span class="s1">','</span><span class="p">,</span> <span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">element</span><span class="p">[</span><span class="s1">'requires'</span><span class="p">]);</span> <span class="k">if</span> <span class="p">(</span><span class="nb">in_array</span><span class="p">(</span><span class="s1">'myrequirement'</span><span class="p">,</span> <span class="nv">$requires</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="nx">MyHelper</span><span class="o">::</span><span class="na">validateRequirement</span><span class="p">())</span> <span class="p">{</span> <span class="k">return</span> <span class="k">false</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> <span class="k">return</span> <span class="k">true</span><span class="p">;</span> <span class="p">}</span> </pre></div> <h2>2. Layouts support</h2> <p>This adds support to use <code>JLayoutFile</code> to render form fields. This is added in <code>JFormField</code> but it doesn't change most of the existing fields to ensure BC. So don't expect it to work out of the box on all the fields. Included fields are:</p> <ul class="task-list"> <li>JFormFieldList</li> <li>JFormFieldUser </li> </ul><p>Now layouts can be defined inside fields setting the property <code>$layout</code>:</p> <div class="highlight highlight-php"><pre> <span class="sd">/**</span> <span class="sd"> * Layout to render</span> <span class="sd"> *</span> <span class="sd"> * @var string</span> <span class="sd"> */</span> <span class="k">protected</span> <span class="nv">$layout</span> <span class="o">=</span> <span class="s1">'joomla.form.field.list'</span><span class="p">;</span> </pre></div> <p>But they also can be overriden on form. Thanks to this we can save to create new fields when the logic to get the data is the same and only the logic to render it changes. Examples would be to load <code>select2</code> on a field for example:</p> <div class="highlight highlight-xml"><pre><span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"show_title"</span> <span class="na">type=</span><span class="s">"list"</span> <span class="na">class=</span><span class="s">"chzn-color"</span> <span class="na">label=</span><span class="s">"JGLOBAL_SHOW_TITLE_LABEL"</span> <span class="na">description=</span><span class="s">"JGLOBAL_SHOW_TITLE_DESC"</span> <span class="na">layout=</span><span class="s">"joomla.form.field.select2"</span> <span class="nt">&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">""</span><span class="nt">&gt;</span>JGLOBAL_USE_GLOBAL<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">"1"</span><span class="nt">&gt;</span>JSHOW<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">"0"</span><span class="nt">&gt;</span>JHIDE<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;/field&gt;</span> </pre></div> <p>Or imagine that you have a layout to render a filed loading <code>typeahead.js</code> field:</p> <div class="highlight highlight-xml"><pre><span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"title"</span> <span class="na">type=</span><span class="s">"list"</span> <span class="na">label=</span><span class="s">"JGLOBAL_TITLE"</span> <span class="na">description=</span><span class="s">"JFIELD_TITLE_DESC"</span> <span class="na">layout=</span><span class="s">"form.field.typeahead"</span> <span class="na">required=</span><span class="s">"true"</span> <span class="nt">/&gt;</span> </pre></div> <p>You can also set a specific layout for the label and layout prefixes/suffixes on your field class:</p> <div class="highlight highlight-php"><pre><span class="sd">/**</span> <span class="sd"> * Layout to render the field label</span> <span class="sd"> *</span> <span class="sd"> * @var string</span> <span class="sd"> */</span> <span class="k">protected</span> <span class="nv">$labelLayout</span> <span class="o">=</span> <span class="s1">'joomla.form.field.label'</span><span class="p">;</span> <span class="sd">/**</span> <span class="sd"> * Prefixes to use to render the field.</span> <span class="sd"> *</span> <span class="sd"> * @var array</span> <span class="sd"> */</span> <span class="k">protected</span> <span class="nv">$layoutPrefixes</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span> <span class="sd">/**</span> <span class="sd"> * Suffixes to use to render the field.</span> <span class="sd"> *</span> <span class="sd"> * @var array</span> <span class="sd"> */</span> <span class="k">protected</span> <span class="nv">$layoutSuffixes</span> <span class="o">=</span> <span class="k">array</span><span class="p">();</span> </pre></div> <p>or in your form XML file:</p> <div class="highlight highlight-xml"><pre><span class="nt">&lt;field</span> <span class="na">name=</span><span class="s">"show_title"</span> <span class="na">type=</span><span class="s">"list"</span> <span class="na">class=</span><span class="s">"chzn-color"</span> <span class="na">label=</span><span class="s">"JGLOBAL_SHOW_TITLE_LABEL"</span> <span class="na">description=</span><span class="s">"JGLOBAL_SHOW_TITLE_DESC"</span> <span class="na">label-layout=</span><span class="s">"joomla.form.field.label2"</span> <span class="na">layout-prefixes=</span><span class="s">"bootstrap3"</span> <span class="na">layout-suffixes=</span><span class="s">"j25"</span> <span class="nt">&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">""</span><span class="nt">&gt;</span>JGLOBAL_USE_GLOBAL<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">"1"</span><span class="nt">&gt;</span>JSHOW<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;option</span> <span class="na">value=</span><span class="s">"0"</span><span class="nt">&gt;</span>JHIDE<span class="nt">&lt;/option&gt;</span> <span class="nt">&lt;/field&gt;</span> </pre></div> <h2>3. Overridable getRenderer</h2> <p>If you want to change the default paths or load your extended class instead of <code>JLayoutFile</code> you can nor override the getRenderer method:</p> <div class="highlight highlight-php"><pre><span class="sd">/**</span> <span class="sd"> * Get the layout used to render the field.</span> <span class="sd"> *</span> <span class="sd"> * @param string $layoutId Layout to render</span> <span class="sd"> * @param mixed $options Optional custom options to load. JRegistry or array format</span> <span class="sd"> *</span> <span class="sd"> * @return JLayoutFile The layout</span> <span class="sd"> */</span> <span class="k">public</span> <span class="k">function</span> <span class="nf">getRenderer</span><span class="p">(</span><span class="nv">$layoutId</span><span class="p">,</span> <span class="nv">$options</span> <span class="o">=</span> <span class="k">array</span><span class="p">())</span> <span class="p">{</span> <span class="nv">$prefixes</span> <span class="o">=</span> <span class="o">!</span><span class="k">empty</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">element</span><span class="p">[</span><span class="s1">'layout-prefixes'</span><span class="p">])</span> <span class="o">?</span> <span class="nb">explode</span><span class="p">(</span><span class="s1">','</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">element</span><span class="p">[</span><span class="s1">'layout-prefixes'</span><span class="p">])</span> <span class="o">:</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">layoutPrefixes</span><span class="p">;</span> <span class="nv">$suffixes</span> <span class="o">=</span> <span class="o">!</span><span class="k">empty</span><span class="p">(</span><span class="nv">$this</span><span class="o">-&gt;</span><span class="na">element</span><span class="p">[</span><span class="s1">'layout-suffixes'</span><span class="p">])</span> <span class="o">?</span> <span class="nb">explode</span><span class="p">(</span><span class="s1">','</span><span class="p">,</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">element</span><span class="p">[</span><span class="s1">'layout-suffixes'</span><span class="p">])</span> <span class="o">:</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">layoutSuffixes</span><span class="p">;</span> <span class="nv">$options</span> <span class="o">=</span> <span class="nb">array_merge</span><span class="p">(</span><span class="k">array</span><span class="p">(</span><span class="s1">'prefixes'</span> <span class="o">=&gt;</span> <span class="nv">$prefixes</span><span class="p">,</span> <span class="s1">'suffixes'</span> <span class="o">=&gt;</span> <span class="nv">$suffixes</span><span class="p">),</span> <span class="nv">$options</span><span class="p">);</span> <span class="k">return</span> <span class="k">new</span> <span class="nx">JLayoutFile</span><span class="p">(</span><span class="nv">$layoutId</span><span class="p">,</span> <span class="k">null</span><span class="p">,</span> <span class="nv">$options</span><span class="p">);</span> <span class="p">}</span> </pre></div> <p>This gives a very flexible tool to developers.</p> <h1>Plugins improvements</h1> <h2>1. Layout support</h2> <p>Now in your plugin you can do something like:</p> <div class="highlight highlight-php"><pre><span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="na">getRenderer</span><span class="p">(</span><span class="s1">'default'</span><span class="p">)</span><span class="o">-&gt;</span><span class="na">render</span><span class="p">(</span> <span class="k">array</span><span class="p">(</span> <span class="s1">'context'</span> <span class="o">=&gt;</span> <span class="nv">$context</span><span class="p">,</span> <span class="s1">'row'</span> <span class="o">=&gt;</span> <span class="nv">$row</span><span class="p">,</span> <span class="s1">'params'</span> <span class="o">=&gt;</span> <span class="nv">$params</span><span class="p">,</span> <span class="s1">'page'</span> <span class="o">=&gt;</span> <span class="nv">$page</span> <span class="p">)</span> <span class="p">);</span> </pre></div> <p>It will search a <code>default.php</code> layout on:</p> <div class="highlight highlight-php"><pre><span class="k">Include</span> <span class="nx">Paths</span><span class="o">:</span> <span class="k">Array</span> <span class="p">(</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">templates</span><span class="o">/</span><span class="nx">protostar</span><span class="o">/</span><span class="nx">html</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">plugins</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">vote</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">=&gt;</span> <span class="o">/</span><span class="k">var</span><span class="o">/</span><span class="nx">www</span><span class="o">/</span><span class="nx">jcms3x</span><span class="o">/</span><span class="nx">layouts</span><span class="o">/</span><span class="nx">plugins</span><span class="o">/</span><span class="nx">content</span><span class="o">/</span><span class="nx">vote</span> <span class="p">)</span> </pre></div> <p><strong>Note:</strong> All the plugins are still using the old hardcoded method. Only the plugin <code>content/vote</code> has been converted for testing purposes.</p> <h2>2. Layouts information on debug</h2> <p>Now the debug console shows all the information of the layouts loaded in the current page:</p> <p><a href="https://camo.githubusercontent.com/2856d4aebcf013eba68d5f4592eb07d2bba80f6a/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313131393237322f323331373633342f64356163363163342d613335312d313165332d383534622d6163616336386536353638612e706e67" target="_blank"><img src="https://camo.githubusercontent.com/2856d4aebcf013eba68d5f4592eb07d2bba80f6a/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313131393237322f323331373633342f64356163363163342d613335312d313165332d383534622d6163616336386536353638612e706e67" alt="layouts-article-form" data-canonical-src="https://f.cloud.github.com/assets/1119272/2317634/d5ac61c4-a351-11e3-854b-acac68e6568a.png" style="max-width:100%;"></a></p> <h1>Testing</h1> <p>Required tests include:</p> <ul class="task-list"> <li>Check that all list fields are shown and work correctly (including tags and all other extending fields)</li> <li>Check that user field works correctly</li> <li>Check that when you enable the option to show votes on articles it's dispalyed correctly</li> <li>Make performance tests with &amp; without this patch to ensure that layouts doesn't overload system.</li> <li>Common layout override tests with prefixes, suffixes, include paths....</li> </ul>
avatar brianteeman brianteeman - change - 8 Aug 2014
Labels Added: ?
avatar brianteeman brianteeman - change - 8 Aug 2014
Labels Added: ?
avatar nicksavov nicksavov - change - 21 Aug 2014
Labels Removed: ?
avatar nicksavov nicksavov - change - 21 Aug 2014
Labels
avatar adster101
adster101 - comment - 1 Sep 2014

Does anyone know what's happening with this PR?

Also, does this work with all form fields or just lists?

avatar wilsonge
wilsonge - comment - 1 Sep 2014

Sorry been meaning to reply to you on the mailing list! Basically we decided to expand the scope a bit and to implement it for the majority of form fields here: https://github.com/joomla-projects/cms-naked

However as you can probably see it lost popularity pretty quick. Me and @phproberto need to chat about what we're gonna do with it!

avatar adster101
adster101 - comment - 1 Sep 2014

Oh okay, it's just that as it stands it's not possible to override the template (without a plugin) to accommodate any other CSS library that BS 2.3.

Would it be possible to just add layouts for the form fields? I can't see any b/c issues in doing this?

Can you point to any examples of where this has been done so that I can see the correct format / style for the overrides etc. I might be able to add them and put in a PR or two if I know what needs to be done.

avatar wilsonge
wilsonge - comment - 1 Sep 2014

Just use this PR as a base example with the rendering of the layouts. Or make a similar PR into the cms-naked branch and I have permissions there to merge that.

I completely agree by the way! I've hacked this into one of my sites to get integrations sorted in the frontend for the editing views.

avatar phproberto
phproberto - comment - 1 Sep 2014

Sorry @adster101 I should also jump into the issue. I was waiting for v3.5 but I think we have to start making that naked CMS.

I'll update the PR against the naked repo tonight and link it here so @wilsonge and me can use it as a starting point to also receive feedback.

Thanks!

avatar brianteeman brianteeman - change - 1 Sep 2014
The description was changed
Status New Pending
avatar brianteeman brianteeman - change - 2 Sep 2014
Category Layout
avatar adster101
adster101 - comment - 3 Sep 2014

What is 'naked' CMS? Is it just a place to add the layouts that will be merged into the staging branch at some point or something else?

@phproberto did you find time to update the repo?

Thanks.

avatar wilsonge
wilsonge - comment - 3 Sep 2014

Yeah so it's a place where we're gonna work on the next layer of making Joomla override-able. Firstly moving as much hardcoded stuff into JLayouts. But also thinking ahead a bit - adding in a getRenderer function (https://github.com/joomla-projects/cms-naked/blob/master/libraries/cms/plugin/plugin.php#L153 ) so that we can investigate not even being dependent on JLayouts.

The idea was that this would go into 3.5 (coming out ~now) but as you probably know 3.4 is being mega late so not quite sure where this is gonna fit in

avatar adster101
adster101 - comment - 3 Sep 2014

Can you elaborate a bit on how the renderer would break the JLayout dependency? I mean what would the other rendering options be?

Is there any reason why this PR can't be merged with 3.4, when it's ready?

avatar Bakual
Bakual - comment - 3 Sep 2014

Can you elaborate a bit on how the renderer would break the JLayout dependency? I mean what would the other rendering options be?

Imho the longtime idea is that you could also use Twig or similar for rendering purposes. At least I understood it like this.

Is there any reason why this PR can't be merged with 3.4, when it's ready?

It could go into 3.4 in theory, but that would be something the release manager (currently for 3.4 that's David Hurley) has to decide. For 3.4, the main focus is a different one and since we're already delayed I wouldn't focus on this one. But if it gets ready in time, maybe it can be merged already.
On the other hand, the stuff in cms-naked is likely going to be a major focus for 3.5. So it would make sense to do this PR together with 3.5.

avatar Fedik
Fedik - comment - 20 Sep 2014

I am a bit play with new JLayoutFile and it really cool thing :guitar:

Have couple suggestions:

1 Posibility to get fullpath without rendering the layout file, something like:

    public function getFullPath()
    {
        if (!is_null($this->fullPath))
        {
            return $this->fullPath;
        }
        // Search
        return $this->getPath();
    }

2 Throw Exception in render() if no layout file found. Currently if no layout found user just get a blank page, that very confused. It not a problem when need to render 1-2 layouts, but when there 100 different layouts can be difficult to find out.

3 What about ability use the priority in addIncludePath()?

Example, I want add own fallback path, so I do

   $layout->addIncludePath('/root/path/my/fallback/path');

And got:

  'includePaths' =>
    array (
      0 => string '/root/path/my/fallback/path'
      1 => string '/root/path/templates/isis/html/layouts' 
      2 => string '/root/path/layouts'
   )

That not really what I want, because I want that my fallback work only when no layout found in the template (or component) folder.
I think something like $layout->addIncludePath('/root/path/my/fallback/path', $priority); would be cool, but I have no idea how this can be done :smile:

added:
I think it can be as b/k solution, for the priority support:

public function addIncludePathToPosition($path, $position = 0)
{
    array_splice($this->includePaths, $position, 0, $path);
    return $this;
}
avatar alex-filat
alex-filat - comment - 6 Dec 2014

Hi,

please ckeck out review of the code of class JLayoutFile

1) Suggest don't run any debug function if debug not requested in options. I undestand that it makes a lot of "if ($this->debug)" but perfomance is more important then pretty code

2) In getPath method call "find" twice

$this->fullPath = JPath::find($this->includePaths, $rawPath);
if ($this->fullPath = JPath::find($this->includePaths, $rawPath))
{
   $this->addDebugMessage('<strong>Found layout:</strong> ' . $this->fullPath);
}
else
{
   $this->addDebugMessage('<strong>Unable to find layout: </strong> ' . $this->layoutId);
}

3) Method JLayoutFile::getPath() checks that file exists so you don't need to check it again in JLayoutFile ::render() method

4) Sugest also make cache on JLayoutHelper::render level from $options passed to render method and keep JLayout instances as value. It will work faster then JLayout cache. As a consequence JLayout's cache can store paths for LayoutId only , without md5 from all options. Some times it also very usefull when developer knows that state of JLayout whould not be changed, so we don't calculate every "render" md5 and json.

avatar dgt41
dgt41 - comment - 7 Jan 2015

What is the decision on this one? If it is ready to commit I would like to bring the fields user, media and content history (versions) to layouts and use bootstrap modal (for protostar and isis) and thus drop completely the loading of mootools on joomla core...

avatar wilsonge
wilsonge - comment - 7 Jan 2015

The decision is that it is being held back for Joomla 3.5 - but the JLayout conversion will be centre feature of that release

avatar dgt41
dgt41 - comment - 7 Jan 2015

Sounds good, thanks George

avatar Fedik
Fedik - comment - 14 Feb 2015

one more note,
I will leave here before forget :smile:
about Prefixes support

suggested search with prefixes is: template with prefix => component with prefix => template without prefix => component without prefix
it make possible case when template override will not work

so I think would be better make search like: template with prefix => template without prefix => component with prefix => component without prefix

avatar phproberto phproberto - change - 16 May 2015
Status Pending Closed
Closed_Date 2014-03-04 09:50:52 2015-05-16 12:26:22
Closed_By phproberto
avatar phproberto phproberto - close - 16 May 2015
avatar joomla-cms-bot joomla-cms-bot - close - 16 May 2015
avatar phproberto phproberto - close - 16 May 2015
avatar joomla-cms-bot joomla-cms-bot - change - 16 May 2015
Labels Added: ?
avatar joomla-cms-bot joomla-cms-bot - change - 16 May 2015
Labels Added: ?
avatar dgt41
dgt41 - comment - 16 May 2015

@phproberto why did you close this one? There’s another approach/solution/code for this?

Add a Comment

Login with GitHub to post a comment