2010-09-24: Converted the bare behavior to a behavior-only plugin for easy git submoduling. Tweaked controller code appropriately.
2010-09-24: Set up a github project. Clone from git://github.com/tomws/replaceable.git into /path/to/project/app/plugins/
I've had this sitting in my project code for a while. After doing a bit of rework today, I thought the concept might be useful to CakePHP noobs (of which I am one).
In my previously posted CakePHP component/helper pair (and more) that displays links in views depending upon ACL permissions, I've added a fake caching system for storing permissions. I call it "fake" caching because I'm not using Cake's cache system at all. Rather, I'm "caching" the user's ACL-permitted actions in his session. Whenever the session is regenerated, the fake cache will be, also. It will also allow forcing of a refresh of the list. First up, here's the code that I drop into app_controller.php:
Sarina sent in a message with a much easier way to use phpBB functions in CakePHP when integrating the users. Apparently, I invent my own complexity sometimes. This is a far better way to code the User model than my sloppy copy/paste method outlined earlier. Here's her code:
Note that you can shorten the model by including the functions directly from phpbb:
2010-10-14: Updated array structure in controller.
There are several articles elsewhere covering this, as well as some (claimed) working solutions. I'm not claiming this is necessarily usable for your project, but it works here under light testing for an app with light user requirements.
Problem: How do I provide only access-permitted links to users in various views? Mark Story released a component a couple of years ago that is supposed to handle it, but either I didn't know what I was doing with it (quite possible) or it just doesn't work under the 1.3 system. I didn't spend much time on it. A search on associated topics revealed Neil Crookes talking about getting and caching all ACOs. That could be useful for checking access, but that's some scary code. The lecterror blog has a greatly simplified version of ACO caching, but after staring at and playing with that code, I found that it won't quite work with my ACO/ARO structure, so it doesn't suit my needs either. Result? Build your own!
I just wasted spent two days off-project because of a variable name change and my git ignorance.
Problems started when trying to use CakePHP's schema generation, which makes versioning the app's database structure (and then rebuilding from that version) quite easy. However, something broke between my last structure update a month ago and the last time I tried earlier this week: the acos table was being dumped from the schema file.
It turns out that there was a change to cake/libs/model/cake_schema.php, but in my gross ignorance of handling CakePHP's core as a git submodule, I was debugging against different versions and (shock!) coming up with inconsistent results. So, first: get your submodules sorted before debugging.
Now, for the root problem. I spent a few hours isolating this, but finally discovered that a commit containing some variable name changes failed to include one of the variable names that needed changing. Seemingly innocuous, this actually resulted in an unintentional clobbering of some output which, in my case, dropped the acos table from the scema.php output from 'cake schema generate'. Bad news, that. But a bug report was quickly taken up and the issue is resolved now.
With that fix and knowing better how to use git for submodules, I've changed core to origin/1.3 in order to incorporate that bug fix. Now everything is working as expected.
In a CakePHP project I'm working on, I'm trying to move into the Git version control system. The Bravo_Kernel blog has an article explaining how to set the whole thing up, which worked fine here. However, I had problems using "cake schema generate" after the setup.
It seems that the cake shells need to receive a command letting them know that the app itself is not in the default location. That's done with the -app argument (run the cake console with no arguments for syntax). My comment over at Bravo_Kernel explains these details, too:
Extra piece of information for anyone else attempting this. I had a problem running a “cake schema generate” on the console after making this change. It wasn’t using the database connection details in my app/config.
The root problem seems to be that when running the console, you need to specify the application path relative to the non-standard cake core path used above (or use an absolute path, if desired). Get your path info by running the cake console with no arguments. Here’s what I got:
Current Paths:
-app: app
-working: /var/www/cakesites/artemis2_cakephp_1.3.0/cakephp/app
-root: /var/www/cakesites/artemis2_cakephp_1.3.0/cakephp
-core: /var/www/cakesites/artemis2_cakephp_1.3.0/cakephp
Apparently, the console works relative to the core rather than determining it’s location through the webroot conf line changed above. In my case, I needed to change the command:
cake schema generate
into:
cake -app ../app schema generate
The schema generation worked fine with that change. I suspect, though haven’t tested, that a “cake bake” (as well as the other shells) would also work incorrectly without the added app argument. I’m not sure if one of the other config options in app/webroot/index.php or elsewhere could be changed to make this unnecessary.
CakePHP's Auth component makes simple authentication fairly easy. However, the project I'm working on could really use some additional data handling in the login process, so I've been trying to modify my User::login() and User::beforeFilter() methods to inject what I need, which I think would involve a manual login attempt using Auth::login().
I've already set [php]$this->Auth->autoRedirect = false;[/php], which is required for anything in User::login() to be executed, but somewhere between beforeFilter() and login(), the password field in $this->data gets emptied and I haven't been able to figure out why. I've guessed that Auth sneaks in there and erases the password field (as hinted at in a few obscure web posts), but have found no definitive answer... until I actually saw this emblazoned in yellow in that autoRedirect section:
The code present in the login function will only execute after authentication was attempted.
If I were one to pile on internet memes, this would be an appropriate placement for a facepalm. So, any logic in User::login() is only useful for post-authentication (attempt) data handling, while User::beforeFilter() apparently must be used for pre-authentication (attempt) logic, Furthermore, pan-authentication (attempt) logic would be unavailable unless one chooses to override Auth::login(), I guess. (Somewhat related, these twoposts describe a way to do that to Auth::identify() without hacking core. I expect I'll be looking at them in the future at some point.)
I'm going to try to split my needed logic into pre- and post- auth chunks and see how that will work out.
UPDATE 20100817: rather than using the [php]'admin' => false[/php] part below, check out [php]$this->params['prefix'] = false[/php]. This seems to work for the prefix routing in the 1.3.x series, which has taken the place of admin routing in the older pre-1.3 versions of Cake.
This confused me for a while because I couldn't find appropriate documentation after much searching. Many CakePHP Auth/Acl tutorials show setting a loginAction like this in a controller's beforeFilter: