-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Single Task Controllers RFC #3503
Single Task Controllers RFC #3503
Conversation
Update master
different repositories for these additions.
|
||
if (!class_exists($class)) | ||
{ | ||
$path = 'com_'.strtolower($prefix).DIRECTORY_SEPARATOR.'view'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need to have DIRECTORY_SEPARATOR here - it should be fine with just a forward slash (which is why J removed the DS constant after 3.5)
@wilsonge Thank you very much for catching the slips. Now all I need to do is figure out how to get past Travis CI. These controllers assume auto-loading, so how can I explain that to Travis? |
directory structure and controller naming conventions. Removed Babelu_lib type hinting in cms/controller/update/copy.php Replaced DIRECTORY_SEPARATOR with "/" in cms/controller/display.php
It's because you have the autoloading of your classes wrong (I think) :P the CMS starts the autoloader in the cms folder. So for the location libraries/cms/controller/base.php it's expecting a class JControllerBase (which it doesn't find) - hence the error. So you need to do two things |
return false; | ||
} | ||
|
||
parent::execute(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd much rather see us return parent::execute in situations like this - because that can return false or true as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. I'll make the change when I wake up tomorrow.
Sincerely,
Mathew Lenning
Babel-university.com
P.S. This message was sent via iPhone, so please forgive any errors
On Apr 26, 2014, at 12:34 AM, George Wilson [email protected] wrote:
In libraries/cms/controller/add.php:
- */
- public function execute()
- {
$config = $this->config;
$prefix = $this->getPrefix();
$model = $this->getModel($prefix, $config['subject'], $config);
if (!$model->allowAction('core.create'))
{
$msg = $this->translate('JLIB_APPLICATION_ERROR_CREATE_RECORD_NOT_PERMITTED');
$url = 'index.php?option='.$config['option'].'&task=display.'.$config['subject'];
$this->setRedirect($url, $msg, 'error');
return false;
}
I'd much rather see us return parent::execute in situations like this - because that can return false or true as wellparent::execute();
�
Reply to this email directly or view it on GitHub.
Thanks! Is there a reason why we aren't including the "cms" in the naming scheme? A true representation of the directory structure seems like it would make the lib easier to navigate (autoloading & human) as well as prevent naming conflicts. I get the reasoning behind libraries/joomla because JJoomla is insane, but CMS specific classes should make that explicitly clear in their name. Sincerely, Babel-university.com P.S. This message was sent via iPhone, so please forgive any errors
|
Well part of it was because we're moving stuff over from libraries/joomla to libraries/cms and making them both as parents was because it kept b/c when we moved stuff across (eventually the joomla folder will be removed and we'll just have the framework classes in the composer vendor folder and the other classes in libraries/cms) |
Because for the |
@Bakual not quite. We still have to load each folder individually the /cms is here https://github.com/joomla/joomla-cms/blob/staging/libraries/cms.php#L30 We just choose to give them all the |
return false; | ||
} | ||
|
||
parent::execute(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same with parent::execute() being returned here
results of parent::execute
So one of the most obvious major issues I see with this is permission checking. Currently we're running the checks like
which is nice for core. But means you have to extend the controller for any extension with it's own permissions section you need to override the whole core permissions structure - which seems excessive. So I'd like to see the permission to be a class variable? Longer term maybe we could even try and think of a way of seeing if the component permissions exist? Finally I'm not a software logic person so i might well be wrong but to me permissions checking belongs in the controller and not the model?? |
Since these controllers are not intended to be overridden putting permission checks in the controller would defeat the purpose, because you would have to override the controller (I.E inherit the controller class) However since the actual check is done in the JUser object, pushing this into a model function allows the developer to do the override there. The permission checks were/are already in the model in legacy, the difference is that now all checks (controller & model) use the same function. This means that to customize the ACL for you only need to do it in one place. Sincerely, Babel-university.com P.S. This message was sent via iPhone, so please forgive any errors
|
Looks like in typical Joomla fashion we split it between controller + model :P (https://github.com/joomla/joomla-cms/blob/staging/libraries/legacy/controller/form.php#L191 - for example). So in that sense I guess as long as we make it consistent. I dunno if anyone knows what's architecturally the right way?? Anyhow my point is the developer cannot override in the model some of the time because the permission to be checked is being defined in the controller (see https://github.com/joomla/joomla-cms/pull/3503/files#diff-b2b39560579bd072dcfeb6bbc1d454bbR39 for example). How in my component foobar I don't want to check |
I think that in order to really grasp what how this design works, one needs to change the way we think about the Model. Most people think of the model as a data provider or an extension of the data layer, but to me the model is more like a dictionary. In the sense that it gives meaning to the terms used in the MVC. The controllers I've built are clueless. They don't know and don't care what the significants of $model->allowAction('core.edit) means, they just want a true or false. This gives the developer the freedom to give meaning without subclassing the controller. An added benefit is that when you need to make these checks in the view (think toolbar) you use the model instead of JFactory::getUser(); Does this make sense? Sincerely, Babel-university.com P.S. This message was sent via iPhone, so please forgive any errors
|
You have to override somewhere to deal with non-standard or generic Given the core.action convention is our standard, I have no issue with that On Fri, Apr 25, 2014 at 8:39 PM, George Wilson [email protected]:
|
Our current system defaults true if permissions aren't explicitly defined IIRC. |
Actually I do want people overriding the model. If they don't want to use core.create then they can translate it to whatever action they like in the model. Since it's consistent throughout the controllers a simple $actions = explode('.', $action); $mycustomeizedaction = whatever.whatever.$actions[1]; Would do the trick, but of course there are a billion ways this could be achieved, so leaving that up to the developer is our best bet. Sincerely, Babel-university.com P.S. This message was sent via iPhone, so please forgive any errors
|
|
I see a lot of "duplicate" (duplicate is not the right word here as it's over a dozen copy-pastested lines of) code, and that's for me an indication of a software architecture issue. |
Are you honestly suggesting there is more copy paste in these controllers than the current implementation? Sincerely, Babel-university.com P.S. This message was sent via iPhone, so please forgive any errors
|
But perhaps I'm miss understanding your comment. Please explain in more detail. Sincerely, Babel-university.com P.S. This message was sent via iPhone, so please forgive any errors
|
$this->validateSession(); | ||
|
||
$config = $this->config; | ||
$url = 'index.php?option='.$config['option'].'&task=add.'.$config['subject']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Be sure to run these through PHP CodeSniffer using the Joomla rules, which can be found here - https://github.com/joomla/coding-standards
For your |
Don't stress about the tests - it's not due to your code - it's a Joomla problem with the tests after travis updated PHPUnit - I have a fix pending for it at #3550 |
@wilsonge Glad to hear it! I was surprised because I don't have any statics methods/classes in either the controllers or the models. @dongilbert I'll run them through the sniffer before I commit tonight. |
…and their proxies in JControllerDispatcher. This should now make chaining and complex interactions easier.
So now we have the ability to do an internal redirect to allow for chaining, but I'm not 100% happy with it yet. |
…line. I'm still still not happy with the name, so if anyone has a good suggestion let me know.
I just want to make one more attempt to show how this design will make life easier for every component developer. I might be kicking a dead horse here, but at least I can say I tried. First lets start with the way we build components now. (admin area only)
Now lets look at the MVSC way
As you can see the MVSC way reduces the number of classes you need to build/maintain from 5 to 2 But the question of how to handle "Special edit tasks" on one view Current Method:
Of course since you had to create the controllers for every view regardless of customization, so overriding them isn't that big of a deal. However different overrides for these functions makes the overall behaviors inconsistent, because depending on the developer the override will be different. MVSC Method
As you can see this isn't much difference between the current MVC and MVSC as far as how to create a custom edit for one view. Except there are more options with MVSC. The real power of this system comes in when we try an use the same functionality in multiple views. Because once we've created the custom task controller we can use it in any view by simply changing the task in our view. There is no need to create a parent class between JControllerForm and extend from it. Also if a third party developer creates a controller that does something awesome, contributing it will be easier because it is independent of all the other controllers. I guess that is the best argument I can give for this for the moment. If anyone has any use cases that they don't think this will work for, then please add a comment explaining it. Explaining how it will make your life easier via examples will be far easier than explaining it off the top of my head. |
Thank you very much Methew! I will study every letter you write and coded and I'm sure more people will seriously look at your work. I'm hitting a deadline (as too often) and unfortunately no time to react immediately. I wanted to let you know, so you know it is no disinterest from my part. Your proposal is very interesting and and has many valuable aspects. I also appreciate it very much that you come with concrete code and examples, which also challenges others to come with concrete counterexamples when having other opinions, as I do have for some parts of your proposal. Together we will get on. Thanks again for code and explanation. |
Thanks Mathew! As a general reply to your last comment: Less files and less (or, even better: no) code copy-pasting for extensions is great news and very valuable in terms of ease of development, maintainability and security. Still need time to get my head into your doc and code proposals and give feedbacks. |
…input param order to match JControllerCms::getModel ordering
…sing the 3.2 version of JTable as a reference. So this will probably have to be refactored.
@HermanPeeren On a side note, THANK YOU for giving me a reason to take another look at PHPStorm! After our conversation, I figured that a hundred bucks would be worth it for the diagramming alone. But after a few days with it, I cannot believe I was coding without it! @beat We might even be able to actually use the 1 to many capability of our view class and push the calling components model into the category view too. I'll link here when I've validated/disproved this possibility. |
Hey @Mathewlenning we are trying to move things forward and make some of your proposals happen. Would you like to join us on a skype group to work on this? If so please add me to skype "phproberto" Thanks!! |
@phproberto Please add me to to a Skype group too, for I'm working on a better proposal (based on this and other proposals). Got some good ideas after talking to several people about Joomla's MVC on JAB. I also assume the Skype workgroup will be in cooperation with the GSOC-project for the new MVC. |
Facebook is a big player in the PHP world. Hence for instance the PHP-compiler they are building (HHVM) and their static typed PHP-variant Hack. And they are refactoring their MVC too. Worth looking at these recent developments. Not in any way intended to derail this discussion, but as inspiration. Video "Hacker Way: Rethinking Web App Development at Facebook", Published on 4 May 2014: https://www.youtube.com/watch?v=nYkdrAPrdcw MVC is the basis of our system at Joomla, so we should take care not to just introduce something without considering the different architectural options we have. For me the starting point must be: what problem do we solve? What are the benefits and the costs of different solutions? |
The two main benefits I'm working from for a newer MVC are:
I'd like to do this as much as possible in a backwards compatible way, so without changing any of the db and when a call to a component would change in any way then make an adapter to keep everything the same. Of course code must be DRY, so fallback principles like used by Mathew and in FOF should be applied: code that is not different from a default should not be coded. |
Good points @HermanPeeren. Can you add me to skype "phproberto" or give me your skype id to add you to the group? |
My Skype-name: herman.peeren |
Thanks for posting those links. I was surprised because the MVSC really resembles flux conceptually. You just have to think of the task controller as the action, the model as the store and well the view is the view. The only partthat isn't implemented is the one cycle at a time imperative, but I do like the idea. There is also the difference in that the view can manipulate the store(model) in MVSC, but I don't think anyone that has been doing this for a while uses more than the get functions in the view. The only real way to prevent the view from changing the model, would be to take the model out. However, I'm using the model as the hub for ACL, so having access to Model::allowAction in the view is a key point. I've been building some components for my site over the last few weeks that use MVSC and the truth is I cannot imagine doing it any other way. 1 model running both list & form on both the front and back without hacking or overriding half the system. The only part that I regret is the choice not to use singleton for the table. In retrospect this is one case that a singleton makes sense. If the next JMVC can top this system, then I am positive that Joomla's troubles will be over. Sincerely, Babel-university.com P.S. This message was sent via iPhone, so please forgive any errors
|
I'm looking forward to seeing your proposal. @phproberto I added you this morning, let me know when the discussions start. Sincerely, Babel-university.com P.S. This message was sent via iPhone, so please forgive any errors
|
I think we've all wasted enough time on this. Happy Joomla!ng |
These are single task controllers that are intended to be used directly. I.E. Not inherited. Each controller is responsible for one task. Extensions can use these controllers to execute each task so long as their model supports the interface the controller expects.
This is a big change compared to the old legacy system where extension developers inherited functionality. The key benefits of this design are:
To understand how this system works please see the dispatcher class as it is the key to the entire system.
Extensions will have to create a controller that extends JCmsControllerDispatcher and then execute it in their extensionName.php entry point.
I've also created model classes that support these new controllers. See https://github.com/Mathewlenning/joomla-cms/tree/CMS-Model-Classes