CakePHP : override BasicAuthenticate.php - cakephp

I'm trying to override lib/Cake/Controller/Component/Auth/BasicAuthenticate.php,
because I need to change the unauthenticated() method.
So I copied and modified the file to app/Lib/Cake/Controller/Component/Auth/BasicAuthenticate.php (also tried without the 'Cake' folder), but the changes are not taken into account.
My edit works when modifying directly the core file but I'd rather not.
How should I do ?
I'm using Cake 2.5

Check if you really need to override a core class
To me this looks like you are on the wrong track, overriding the class shouldn't be neccesary unless for example you have no controler over where and how the basic authentication adapter is being used (for example in a plugin that doesn't offer configuration).
If you'd really need to overwrite the class, then the path should be
app/Lib/Controller/Component/Auth/BasicAuthenticate.php
and it should work just fine (it does for me, using CakePHP 2.5.6).
http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#overriding-classes-in-cakephp
Use a custom authentication handler instead
If you have control over the adapter configuration, the I'd suggest that you extend the BasicAuthenticate class instead, and only override the unauthenticate() method, and finally make the auth component use the custom adapter.
Something like
app/Controller/Component/Auth/CustomBasicAuthenticate.php
App::uses('BasicAuthenticate', 'Controller/Component/Auth');
class CustomBasicAuthenticate extends BasicAuthenticate {
public function unauthenticated(CakeRequest $request, CakeResponse $response) {
// do something special
}
}
Controller
public $components = array(
'Auth' => array(
'authenticate' => array(
'CustomBasic'
)
)
);
See also the Creating Custom Authentication objects section in the Cookbook.

Related

calling plugin's controller from AppController in CakePHP 3

I have written a plugin for CakePHP 3.4.*.
This plugin will check for Database configuration has been set or not, if not then It you move user through a GUI interface to setup database configuration just like wordpress.
The plugin is working perfectly, but it has to be loaded manually by visiting url of the plugin
http://example.com/installer/install
where installer is the plugin name which is calling InstallController class inside plugins/Installer/src/Controller/ directory
Now what I want to check it automatically and redirect user to the Installation interface if database connection couldn't be established.
For that I have written a function inside InstallController of plugin's controller
public function installationCheck() {
$db = ConnectionManager::get('default');
if(!$db->connect()) {
if(Configure::read('Database.installed') == true) {
$this->Flash->error(__("Database connection couldn't be established. Please, re-configure it to start the application"));
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error(__("Please configure your database settings for working of your application"));
return $this->redirect(['action' => 'index']);
}
}
return true;
}
Now the Question.
What is the easiest way to call this method from /app/src/Controller/AppController.php file of the main application?
Simple answer, you don't!
Shared controller logic belongs either in AppController itself, a Component or a Trait. The AppController should never being accessing methods defined in other controllers, these shouldn't be made accessible to it.
For what you're doing you probably want to do this in a component that you can load via your AppController or the relevant controller.
So your component would look something like:-
<?php
namespace Installer\Controller\Component;
use Cake\Controller\Component;
class InstallComponent extends Component
{
public function installationCheck()
{
// Method's logic
}
}
Which you would then load in the relevant controller:-
public function initialize()
{
parent::initialize();
$this->loadComponent('Installer.Install');
}
Then you can use the component's method from the controller like:-
$this->Install->installationCheck();
You should not Do that!
If you need to access another controller I recommend you to move that functionality to a Component, that are packages of logic that are shared between controllers.

Cache View in CakePHP 3.0

I understand that we can cache an action or view page in CakePHP 2.0. Refer to this link http://book.cakephp.org/2.0/en/core-libraries/helpers/cache.html.
class PostsController extends AppController {
public $helpers = array('Cache');
}
public $cacheAction = array(
'view' => 36000,
'index' => 48000
);
However, it seems that CakePHP 3.0 has removed helper(http://book.cakephp.org/3.0/en/core-libraries/caching.html). Is there any other way in CakePHP 3.0 I can cache the view page. For example, I have a index view/action. And I would like to cache that page. Thanks.
Is there any other way in CakePHP 3.0 I can cache the view page.
Not without developing something yourself. Like for example saving the rendered content to a file in callback for Dispatcher.afterDispatch event and then checking for the file in callback for Dispatcher.beforeDispatch event and returning the cached response.
Better to use you something like Varnish which is more suited for the job.

How to access parameters passed to Component from AppControler in CakePHP 2.4

I have created a component called ApiComponent to handle opening an HttpSocket to another server to post information. It looks like this:
class ApiComponent extends Component {
public function connect($endpoint,$data) {
App::uses('HttpSocket', 'Network/Http');
$HttpSocket = new HttpSocket();
// rest of the code
}
}
This works in the sense that I can call $this->Api->connect('/posts/add.json',$data); from my controller and the code is executed as expected.
However, I have a lot of settings in the $HttpSocket->request such as the hostname, port number, username, password etc etc that I'd like to take out of the Component and put in a config file.
According to http://book.cakephp.org/2.0/en/controllers/components.html#including-your-component-in-your-controllers I can pass parameters to the Component from the AppController like this:
public $components = array(
'Api' => array(
'host' => 'localhost',
'port' => '80'
),
'Session', 'Auth'
);
The manual says that this would pass the array to ApiComponent::__construct() but it doesn't say how I'm supposed to access the data in the component (or, it may... I'm in unfamiliar territory here).
So, my questions are:
1) Is it appropriate to put things like host, username, password etc in the AppController like this? And...
2) ...if so, how do I access them from within the Component?
...or...
3) ...if not, where exactly should I place settings like this?
In your ApiComponent your settings are stored in:
$this->settings
see API
I don't fully agree with #Lionel Chan: I don't think it's such a bad idea to store that values in the Component settings. But also using Configure class is a good practice.
No, it's not appropriate (so it's unclear). Controllers are for system/business logic, not for configurations.
(and 3.) You can probably use the following methods to store configurations:
Good, old constant way:
It's easy, just define(key, value) these credentials in your bootstrap.php and you should be fine, and it's globally accessible.
Use Configure class
Configure is pretty handy as it's global to CakePHP. You simply do Configure::write() to write the credentials in your bootstrap.php file. Yes it will have some minor overheads if you don't mind, but should not be noticeable.

CakePHP administrator routing

I am having a hard time to understand this admin-routing of CakePHP. From the Cookbook:
"You can map the url /admin to your admin_index action of pages controller using following route:"
Router::connect('/admin', array('controller' => 'pages', 'action' => 'index', 'admin' => true));
What is not clear to me is the "'admin' = true". What is the purpose of this? When you call logout-function, do you pass the argument "'admin' = false" to redirect function in AppController?
When you have multiple prefixes in use, do you use "'manager' = true" if you want to enable manager-prefix?
admin=true in a route means your url is prefixed with /admin.
So in your example, your /admin route actually connects to: /admin/pages/index, and is serviced by the admin_index() action in your pages controller (as opposed to the non-prefixed index() action).
You can either ensure all links to logout are created with admin=false so they map to the standard Users::logout() action, or create a new action admin_logout() which handles admin logouts.
Adding manager=true to a url (along with the associated prefix setting) means the url with begin with /manager, and will map to manager_...() functions in the controller.
You can use both (or more!) prefixes, but not in the same url.
/pages/index maps to: PagesController:index();
/admin/pages/index maps to: PagesController:admin_index();
/manager/pages/index maps to: PagesController:manager_index();
Router Prefixes
In CakePHP 2.x prefixes changed a little.
You can have multiple prefixes now, but they have to be declared in the core.php file.
Configure::write('Routing.prefixes', array('admin','api','json'));
That would declare 3 prefixes, and there is no need to modify the routing tables to make them work. The word prefix means it's placed before the name of the action when dispatching to the controller.
For example;
class DocumentsController extends AppController
{
public index() { ... }
public admin_index() { ... }
public api_index() { ... }
public json_index() { ... }
}
CakePHP will call the correct action when one of these URLs are request.
http://example.com/documents/index
http://example.com/admin/documents/index
http://example.com/api/documents/index
http://example.com/json/documents/index
What you can not do is use more than one prefix at a time. The following will NOT work.
http://example.com/admin/json/documents/index
That would require custom routing, because CakePHP doesn't know which action to call.
When an action is called you can which for prefixes in the request params.
public function beforeFilter()
{
if(isset($this->request->params['admin']))
{
// an admin prefix call is being made
}
}

Extends cakephp plugin

I'm using spark_plug plugin on cakephp, this plugin provides an authentication-acl system for register and admin users in cakephp. I want to add some new code and functionalities to the user's controller but I don't want to change the "main" plugin files.
I was thinking if it is possible leave the "main" plugin controller as it (unchanged) "\app\plugins\spark_plug\controllers\users_controller.php" and create a secondary controller with all the new code and functionalities, something like this "\app\controllers\users_controller.php" and extends the plugin "main" controller.
Is that possible? and how achieve that?
Or do you think is there any other way to do what I want?
Thanks!
You could perhaps use composition rather than inheritance? I.e. create a "app\controllers\users_controller" that has inside it an instance of the plugin's controller. The UsersController passes through any unmodified actions via stubs, eg:
class UsersController extends AppController {
...
var spark_plug_users_controller;
...
public function __construct() {
parent::__construct();
App::import('Controller', 'SparkPlug/Users'); // this is probably wrong.
$this->spark_plug_users_controller = new UsersController; // as is this.
$this->spark_plug_users_controller->constructClasses();
}
...
//example non-overridden method
function login() {
return $this->spark_plug_users_controller->login();
}
...
}
your problem would be accessing protected/private methods within the spark_plug Users controller. But if you did not need to, this may work.

Resources