Accessing Arguments using $_GET - atk4

I am adding an email validation step to my user registration. I cannot seem to get access to the arguments that are being passed in the emailed link;
link: activation.php?email=someone#somewhere.com&key=5614c46be05a95f55f2231d8dea41418d17b197a
Here is the page code;
class page_activation extends Page {
function init(){
parent::init();
if($this->api->auth->isLoggedIn())$this->api->redirect('index');
$loginAccount = $_GET['email'];
$activationKey = $_GET['key'];
$this->add('H1')->set('Activated');
$this->add('H3')->set('Account: '.$loginAccount);
$this->add('H3')->set('Key: '.$_GET['key']);
}

var_dump($_GET);
check network tab in inspector to make sure get params are actually passed.
check mod rewrite rules

I have found a solution in case it might help someone. It seems you can access the $_SERVER vars but the $_GET vars are lost by the time you get to the page. Here is some code that I used to accesses the passed vars from the email link;
class page_activation extends Page {
function init(){
parent::init();
if($this->api->auth->isLoggedIn())$this->api->redirect('index');
$data = parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY);
$queryParts = split('[;&]', $data);
$params = array();
foreach ($queryParts as $param) {
$item = explode('=', $param);
$params[$item[0]] = $item[1];
}
$loginAccount = $params['email'];
$activationKey = $params['key'];
$this->add('H1')->set('Activated');
$this->add('H3')->set('Account: '.$loginAccount);
$this->add('H3')->set('Key: '.$activationKey);
}
}

Related

CakePHP3 Render View to a Variable

I want to render the view to a variable without directly sending it to the browser. I used to do it with cakephp2.*. But, I cannot figure out how to do it in CakePHP3. Could you please tell me how to do it?
ViewBuilder was introduced in CakePHP 3.1 and handles the rendering of views. When ever I want to render to a variable I always go look at how send email works.
From a controller:
function index() {
// you can have view variables.
$data = 'A view variable';
// create a builder (hint: new ViewBuilder() constructor works too)
$builder = $this->viewBuilder();
// configure as needed
$builder->layout('default');
$builder->template('index');
$builder->helpers(['Html']);
// create a view instance
$view = $builder->build(compact('data'));
// render to a variable
$output = $view->render();
}
For Ajax request/response, I use this:
public function print(){
if ($this->request->is('ajax')) {
$data = $this->request->getData();
$builder = $this->viewBuilder()
->setTemplatePath('ControllerName')
->setTemplate('print');
->setLayout('ajax');
->enableAutoLayout(false);
$view = $builder->build(compact('data'));
$html = $view->render();
$res = ['html' => $html];
$this->set('response',$res);
$this->set("_serialize",'response');
}
}
And the print.ctp is under Template/ControllerName

cant add paramater when caling view with search function in cakephp

In cakephp I have a search function which uses parameters and call backs. My issue is that I want to call this function with a parameter but the function cant accept parameters when called.
//I cant call this function with a paramater
$this->redirect(array('action' => 'email_list',$id,));
....
public function email_list($search = 0) {
$this->set( 'search',$search);
;
if (($this->request->is('post') || $this->request->is('put'))) {
if (isset($this->request->data['searchFilter'])) {
$filter_url['controller'] = $this->request->params['controller'];
$filter_url['action'] = $this->request->params['action'];
$filter_url['page'] = 1;
// for each filter we will add a GET parameter for the generated url
foreach($this->data['User'] as $name => $value){
if($value){
$filter_url[$name] = urlencode($value);
}
}
//Post params are now GET paramaters
return $this->redirect($filter_url);
}//isset
worked out a solution using a session variable that gets destroyed on entry. It is quick and easy. Having to redo a search function in cakephp ver 2 is not something i want to do. I am updating to cakephp ver 3
public function email_list($search = 0) {
if ($this->Session->check('sessrowid'))
{
$searchRowId=$this->Session->read('sessrowid');
$this->Session->delete('sessrowid');
}

CakePHP URL Parameter

How can I get the parameter in the URL and save it to a varialble so I can save it to my database?
example: www.mydomain.com/item/products/3 <-
This is for my upload image, so I can specify what product ID will I use for that image.
function add() {
if ($this->request->is('post')) {
$this->Upload->create();
if(empty($this->data['Upload']['image']['name'])) {
unset($this->request->data['Upload']['image']);
}
if(!empty($this->data['Upload']['image']['name'])) {
$filename = $this->request->data['Upload']['image']['name'];
$new_filename = STring::uuid().'-'.$filename;
$file_tmp_name = $this->request->data['Upload']['image']['tmp_name'];
$dir = WWW_ROOT.'img'.DS.'uploads';
move_uploaded_file($file_tmp_name,$dir.DS.$new_filename);
$this->request->data['Upload']['image'] = $new_filename;
if($this->Upload->save($this->request->data)) {
$this->Session->setFlash(__('Uploaded.'));
$this->redirect(array('action' => 'index'));
}
}
}
}
How will I add it here. Thank you in advance :)
Im using cakePHP
Just add the product id as a hidden input in the Form.
Then it will be included in the $this->data variable when you get the POST request.
For example in a controller method like the following
public function product($id) {
.....
}
You access it by the url (for example): www.mydomain.com/item/products/3 where Item is the controller, product is the method you are calling in that controller and 3 represent a parameter that is required to the function to work in this case $id. (assuming you don't have any routing configuration)
Is treated as a normal php variable, just do whatever you wanna do with it. Just make sure you pass the correct value

cakephp PaginationRecall component crashes my application with a different url/pages

The PaginationRecall component is giving me a headache, it let my application crash.
I have a region view, I can call it with /views/[number of region]
I found out that the reason for the crash is that it wants to go back to Page:5
although the url is changed to a different region which only has 1 or 2 pages.
I updated to the latest cakePHP version [v2.3.5] as there was a mention about a fix for 'Preventing pagiation limit from overflowing the max integer value' But updating didn't solve my problem. Not sure if this is a problem with the PaginationRecal component or the Paginator itself.
For example; I can browse to the url ../regions/view/1/page:5 leave that page and when return back all fine [it remembered last page]
But when changing the url to a different region ../regions/view/56/ it crashes with error: Error: The requested address '/regions/view/56' was not found on this server.
Stack Trace
CORE/Cake/Controller/Controller.php line 1074
#deprecated Use PaginatorComponent instead
*/
public function paginate($object = null, $scope = array(), $whitelist = array()) {
return $this->Components->load('Paginator', $this->paginate)->paginate($object, $scope, $whitelist);
}
At first I didn't understand this crash untill I found out it was related to the page number. The problem never pops-up when browsing only on the first page. How can I fix this problem?
I have added the PaginatorRecall Component in my /app/Controller/AppController.php
public $components = array('PaginationRecall');
This is the component: http://bakery.cakephp.org/articles/Zaphod/2012/03/27/paginationrecall_for_cakephp_2_x
Any help much appreciated.
SOLVED
After investigating what the PaginatorRecall component is doing, I found out that it filters out only the page:number and stores it in a session.
I have added a rule to find out if the region is changed and if so then reset the page to page:1
Hope this helps someone else using this component as well.
This is my solution to this problem and the bug that PaginationRecall have with the first page. Surely it is not the most optimal solution, but it is functional.
class PaginationRecallComponent extends Component {
var $components = array('Session');
var $Controller = null;
function initialize(&$controller) {
$this->Controller = & $controller;
$options = array_merge($this->Controller->request->params, $this->Controller->params['url'], $this->Controller->passedArgs
);
$vars = array('page', 'sort', 'direction', 'filter');
$keys = array_keys($options);
$count = count($keys);
for ($i = 0; $i < $count; $i++) {
if (!in_array($keys[$i], $vars) || !is_string($keys[$i])) {
unset($options[$keys[$i]]);
}
}
//save the options into the session
if ($options) {
if ($this->Session->check("Pagination.{$this->Controller->modelClass}.options")) {
$options = array_merge($this->Session->read("Pagination.{$this->Controller->modelClass}.options"), $options);
}
$this->Session->write("Pagination.{$this->Controller->modelClass}.options", $options);
$this->Session->write("region",$this->Controller->modelClass.'/'.$this->Controller->view);
}
$region=$this->Session->read('region');
//recall previous options
if ($this->Session->check("Pagination.{$this->Controller->modelClass}.options") && $region==$this->Controller->modelClass.'/'.$this->Controller->view ) {
$options = $this->Session->read("Pagination.{$this->Controller->modelClass}.options");
if(!isset($this->Controller->params['named' ]['page']) && isset($this->Controller->params['named' ]['direction']) )
{
$options['page']=1;
}
$this->Controller->passedArgs = array_merge($this->Controller->passedArgs, $options);
$this->Controller->request->params['named'] = $options;
}
}
}

Cakephp 2.0 change password

I am attempting to create a change password form in cakephp 2.0. I found a behavior that EuroMark created for 1.3 and now am having a tough time converting this code to work with 2.0. I know that it has something to do with the Auth Component as there were major changes to this component in 2.0.
public function validateCurrentPwd(Model $Model, $data) {
if (is_array($data)) {
$pwd = array_shift($data);
} else {
$pwd = $data;
}
$uid = null;
if ($Model->id) {
$uid = $Model->id;
} elseif (!empty($Model->data[$Model->alias]['id'])) {
$uid = $Model->data[$Model->alias]['id'];
} else {
return false;
}
if (class_exists('AuthExtComponent')) {
$this->Auth = new AuthExtComponent();
} elseif (class_exists($this->settings[$Model->alias]['auth'].'Component')) {
$auth = $this->settings[$Model->alias]['auth'].'Component';
$this->Auth = new $auth();
} else {
return true;
}
return $this->Auth->verifyUser($uid, $pwd);
}
I am getting an error on the line that reads $this->Auth = new $auth();
The error is as follows:
Argument 1 passed to Component::__construct() must be an instance of ComponentCollection, none given, called in C:\UniServer\www\new_company_test\app\Model\Behavior\change_password.php on line 117 and defined [CORE\Cake\Controller\Component.php, line 77]
and
Undefined variable: collection [CORE\Cake\Controller\Component.php, line 78]
it's also throwing this
Call to undefined method AuthComponent::verifyUser() in C:\UniServer\www\new_company_test\app\Model\Behavior\change_password.php on line 121
I am not sure if there is anything else that needs to be addressed in the script, I'm guessing not as there is no other place where Auth is used.
Any suggestions on what I need to do to get this to work? Any help is appreciated.
Thanks
you did discover that there is also a 2.0 branch, didnt you? :)
it should contain the same behavior:
https://github.com/dereuromark/tools/tree/2.0
either way, you need to pass a component collection into it:
$this->Auth = new AuthExtComponent(new ComponentCollection());
You should create a method verifyUser in your custom AuthExt Component which extends Auth Component for "current password" to work like so:
/**
* Quickfix
* TODO: improve - maybe use Authenticate
* #return bool $success
*/
public function verifyUser($id, $pwd) {
$options = array(
'conditions' => array('id'=>$id, 'password'=>$this->password($pwd)),
);
return $this->getModel()->find('first', $options);
$this->constructAuthenticate();
$this->request->data['User']['password'] = $pwd;
return $this->identify($this->request, $this->response);
}
/**
* returns the current User model
* #return object $User
*/
public function getModel() {
return ClassRegistry::init(CLASS_USER);
}
Maybe it is also possible to use the existing identify method in combination with a fake request object in the behavior directly?
I am thinking about using
$this->authenticate = array('Form'=>array('fields'=>array('username' => 'id')));
feel free to fork the behavior and submit a pull request.
"current password" is the only thing that is not yet cleanly solved right now.

Resources