Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

fix JModelLegacy __construct method to determine option #1500

Merged
merged 3 commits into from

7 participants

@dongilbert
Collaborator

Line 216 of JModelLegacy will incorrectly parse your model class name if your model class ends in model. I had a situation where I was building an auto manager for a client, and one of the models was named AutosModelModel. The current regex parsed the classname and thought that the option was com_autosmodel, because it doesn't take into account the possibility that a model class can end in model.

This pull request address issue #1499

Note: This fix breaks backwards compatibility (potentially) because previously the regexp used the /i modifier, searching for case-insensitive strings. This new implementation uses case-sensitive strpos. Make sure your class names are properly CamelCased. (http://docs.joomla.org/Coding_style_and_standards#Classes)

@ianmacl

I'm fine with this if somebody from the CMS can stamp their approval on it.

@dongilbert
Collaborator

I have a pull request pending there as well as a tracker item.

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

@elinw

Could we also do the same for view?

@dongilbert
Collaborator

Where are you referring to make this change? The only thing close I can find is https://github.com/dongilbert/joomla-cms/blob/master/libraries/joomla/application/component/view.php#L547

Is that what you mean?

@mbabker
Owner

In the current Platform code, the method is here: https://github.com/joomla/joomla-platform/blob/staging/libraries/legacy/view/legacy.php#L444

Fixing the regex for JViewLegacy should hopefully allow us to rename this CMS class to the proper name: https://github.com/joomla/joomla-cms/blob/master/administrator/components/com_templates/views/prevuuw/view.html.php#L19

@dongilbert
Collaborator

Thanks for the links. I'll work on that. Should it be a separate pull request though? I think so, as what's implemented here is functioning independent of the view regex.

@dongilbert
Collaborator

@mbabker @elinw - can you test this? https://github.com/dongilbert/joomla-platform/compare/jviewgetname.diff

I've done some testing and received expected results.

This is how I tested - https://gist.github.com/3563618

#1509

@pasamio

Actually the current regexp supports TemplatesViewPreview just fine, it's been fixed for a while just the view hasn't been renamed. You can test it and see.

@pasamio

Ok, I double checked while the regexp supports it, the check if the view name that we found includes view is what kills it for some reason.

@dongilbert
Collaborator

This discussion got a little sidetracked from this pull request to another one concerning JViewLegacy. What's everyone's thought on this one?

@eddieajau

Is there any reason why you can't remove the regex and use the same technique as in JViewLegacy?

@dongilbert
Collaborator

Ya - I thought that same thing and just pushed it.

@dongilbert dongilbert fix JModel __construct regex to determine option
dropped regexp in favor of strpos

Updating JModelLegacy::getName with same technique
0a7653a
@dongilbert
Collaborator

I also updated the getName method here with the same technique. Squashed and pushed last 3 commits

@dongilbert
Collaborator

I've been testing this locally with no issues, but I would like (for obvious reasons) some others to test as well. Any takers?

@elinw

It's one of those unfair situations because it's not your fault that there are not tests (and if there were someone would have thought about doing this a long time ago) but if you could do a little bit of test writing that would be awesome.
https://github.com/joomla/joomla-platform/blob/staging/tests/suites/legacy/model/JModelLegacyTest.php

@pasamio now you know why I asked about view (even though we pulled that view anyway).

@dongilbert
Collaborator

Gotcha - I guess my first go at unit testing is about to take place. :) I've read about it a lot, but haven't created any unit tests yet. Here's my shot.

@LouisLandry

@dongilbert for what it's worth I really like the change. I look forward to reviewing this when you get the tests sorted out. If you need help getting those done please feel free to ask either on list or in this pull request any questions you may have.

I'm going to close this request for now while we wait for you to get those tests sorted out. Please note that this isn't due to rejecting the request, but just a matter of keeping our pull request queue free of things not actively needing review. When you get the unit tests sorted out just re-open the request and we'll go from there. Thanks a bunch for the initiative and the work.

@LouisLandry LouisLandry closed this
@dongilbert
Collaborator

I've been struggling with the tests, as I wasn't sure if I should use mock classes for the model, or just create some class name strings to use.

Also, I just set up a new computer, and don't have phpunit installed yet. I was going to install via composer, because I didn't really want to install the pear library. However, I don't think PHPCS has composer support yet, so I may have to install pear after all.

@dongilbert
Collaborator

Also, what PHPUnit optional packages are needed for testing the Joomla Platform

@LouisLandry

I tend to just set mine up with the directions at: http://jenkins-php.org

That gets pretty much the full compliment of tools I use for static analysis and testing (including PHP_CodeSniffer). As for dependencies the only think I can think of that you may need to install extra is phpunit/DbUnit. I don't remember if it comes packaged or not.

You can follow the instructions in the readme at: https://github.com/joomla/coding-standards to install our standard once you have PHP_CodeSniffer installed.

@dongilbert
Collaborator

Thanks Louis - that helped.

So what are your thoughts on creating the tests - Should probably just use strings of potential class names for testing, rather than mock models, right?

Also, this should only include tests relative to the pr, instead of the full on JModelLegacy testing that still needs to be completed. (Which I think, since I'm in there, I'll probably complete)

@LouisLandry

I think you are on the right track. One of the principles of good unit testing is to really isolate the exact "unit" of code you are testing. In this case really you are wanting to test the class name evaluation, so if you can avoid having to create a whole bunch of test classes, etc then that is the preferred path.

For this pull request we only really need tests for the changes being made on this pull request. If you wanna have a go at the rest, my suggestion is to do them separately in a separate branch so as to not let that work get in the way of getting this stuff done and merged. That being said, if you want to just go for it that is entirely up to you.

@dongilbert
Collaborator

I can't run the test suite against the legacy tree, not sure what's going on there - I may have borked my installation by merging joomla-platform/master

@dongilbert
Collaborator

It doesn't appear as though PHPUnit is running the legacy test suite. It's not specified in the phpunit.xml.dist

@LouisLandry

Try running phpunit -c legacy.xml.dist to have it run the legacy suite.

@dongilbert
Collaborator

That works much better! Thanks - Now I can start actually writing the tests.

@dongilbert
Collaborator

I've got the tests ready, how do I reopen a pull request? Just send in another one?

@eddieajau

Should be a "Reopen" button at the bottom of the page?

@LouisLandry

Also, you need to merge your new commits into the jmodelfix branch and push it up to github so that they show up in this pull request.

@dongilbert
Collaborator
@dongilbert
Collaborator
@dongilbert
Collaborator

I double checked and I did push it to the correct branch. Also, there is definitely not a reopen button at the bottom of this page.

@eddieajau

So, turns out only maintainers can re-open sigh Best laid plans of mice and men and all that :) Re-opening.

@eddieajau eddieajau reopened this
@dongilbert
Collaborator

Ya. Funny. I wonder if after we build this new issue tracker if we could build in the ability for users to submit an issue for re-opening.

The tests have been completed and added. I'm going to add the rest of the tests after this has been verified. ( since its my first experience with unit tests)

@LouisLandry

All passes! Thanks a bunch for your patience and work through this @dongilbert.

@LouisLandry LouisLandry merged commit 6d6c331 into joomla:staging
@dongilbert
Collaborator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 3, 2012
  1. @dongilbert

    fix JModel __construct regex to determine option

    dongilbert authored
    dropped regexp in favor of strpos
    
    Updating JModelLegacy::getName with same technique
Commits on Oct 9, 2012
  1. @dongilbert

    adding unit tests

    dongilbert authored
This page is out of date. Refresh to see the latest.
View
16 libraries/legacy/model/legacy.php
@@ -211,14 +211,15 @@ public function __construct($config = array())
// Guess the option from the class name (Option)Model(View).
if (empty($this->option))
{
- $r = null;
+ $classname = get_class($this);
+ $modelpos = strpos($classname, 'Model');
- if (!preg_match('/(.*)Model/i', get_class($this), $r))
+ if ($modelpos === false)
{
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500);
}
- $this->option = 'com_' . strtolower($r[1]);
+ $this->option = 'com_' . strtolower(substr($classname, 0, $modelpos));
}
// Set the view name
@@ -387,12 +388,15 @@ public function getName()
{
if (empty($this->name))
{
- $r = null;
- if (!preg_match('/Model(.*)/i', get_class($this), $r))
+ $classname = get_class($this);
+ $modelpos = strpos($classname, 'Model');
+
+ if ($modelpos === false)
{
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_MODEL_GET_NAME'), 500);
}
- $this->name = strtolower($r[1]);
+
+ $this->name = strtolower(substr($classname, $modelpos + 5));
}
return $this->name;
View
25 tests/suites/legacy/model/JModelLegacyTest.php
@@ -7,11 +7,19 @@
* @license GNU General Public License version 2 or later; see LICENSE
*/
+class TestModelLead extends JModelLegacy
+{
+}
+
+class RemodelModelRoom extends JModelLegacy
+{
+}
+
/**
* Test class for JModelLegacy.
*/
-class JModelLegacyTest extends PHPUnit_Framework_TestCase
-{
+class JModelLegacyTest extends TestCase
+{
/**
* @todo Implement testGetInstance().
*/
@@ -62,8 +70,17 @@ public function testSetDbo()
*/
public function testGetName()
{
- // Remove the following lines when you implement this test.
- $this->markTestIncomplete('This test has not been implemented yet.');
+ $class = JModelLegacy::getInstance('Lead', 'TestModel');
+ $this->assertEquals('lead', $class->getName());
+ $this->assertEquals('com_test', TestReflection::getValue($class, 'option'));
+
+ $class = JModelLegacy::getInstance('Room', 'RemodelModel');
+ $this->assertEquals('room', $class->getName());
+ $this->assertEquals('com_remodel', TestReflection::getValue($class, 'option'));
+
+ TestReflection::setValue($class, 'name', 'foo');
+ $this->assertEquals('foo', $class->getName());
+ $this->assertEquals('com_remodel', TestReflection::getValue($class, 'option'));
}
/**
Something went wrong with that request. Please try again.