Can i write single method in CodeIgniter Controller to handle both GET and POST login form? - codeigniter-3

In web application we are using POST and in IPAD we are using GET to submit form details. But I written both GET and POST method in my CodeIgniter Controller. But it's not good because I'm maintaining same code twice in Cotroller?
Current Code:
class LoginHandle extends REST_Controller
{
public function authenticate_post()
{}
public function authenticate_post()
{}
}
Is is possible some thing like following?
class LoginHandle extends REST_Controller<br>
{
public function authenticate_get_post()
{}
}

As I expect there aren't many form items to check - you could use (assuming PHP7+) the ?? operator like this:
$username = $_POST['User'] ?? $_GET['User'];
$password = $_POST['Pass'] ?? $_GET['Pass'];
For PHP < 7 you can use ...
$username = !empty($_POST['User']) ? $_POST['User'] : !empty($_GET['User']) ? $_GET['User'] : null;
$password = !empty($_POST['Pass']) ? $_POST['Pass'] : !empty($_GET['Pass']) ? $_GET['Pass'] : null;

Please, see: https://www.codeigniter.com/user_guide/libraries/input.html#CI_Input::post_get
$this->input->post_get('key')

Related

Shopware 6 : How to get dynamic url in custom plugin controller?

Shopware 6
I am new to shopware. I want base url in controller ( custom plugin ).
I tried this but it's not working for me.
$salesChannel->getDomains()->first()->getUrl();
Thanks in advance
If you just need the current host and base url in your controller:
use Shopware\Storefront\Framework\Routing\RequestTransformer;
use Symfony\Component\HttpFoundation\Request;
// ...
/**
* #Route(...)
*/
public function myAction(Request $request): Response
{
$host = $request->attributes->get(RequestTransformer::SALES_CHANNEL_ABSOLUTE_BASE_URL)
. $request->attributes->get(RequestTransformer::SALES_CHANNEL_BASE_URL);
// ...
}
First : Add this namespace
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
Second : here you can get base url.
$urls = [];
$salesChannelRepository = $this->container->get('sales_channel.repository');
$criteria = new Criteria();
$criteria->addAssociation('domains');
$salesChannelIds = $salesChannelRepository->search($criteria, Context::createDefaultContext());
foreach($salesChannelIds->getEntities()->getElements() as $key => $salesChannel){
foreach($salesChannel->getDomains()->getElements() as $element){
array_push($urls, $element->getUrl());
}
}
you will get your url in $urls variable.
If you have access to the request object which you should have in a controller, you have access to an request attribute called sw-storefront-url. This will give you exactly what you need: the base-url of the current request.
See also How to get the current saleschannel domain in Shopware 6 storefront/TWIG?

How to test form request rules in Laravel 5?

I created a form request class and defined a bunch of rules. Now I would like to test these rules to see if the behaviour meets our expectations.
How could I write a test to accomplish that?
Many thanks in advance for your answers!
Update: more precisely, I would like to write a unit test that would check e.g. if a badly formatted email passes validation or not. The problem is that I don't know how to create a new instance of the Request with fake input in it.
The accepted answer tests both authorization and validation simultaneously. If you want to test these function separately then you can do this:
test rules():
$attributes = ['aa' => 'asd'];
$request = new MyRequest();
$rules = $request->rules();
$validator = Validator::make($attributes, $rules);
$fails = $validator->fails();
$this->assertEquals(false, $fails);
test authorize():
$user = factory(User::class)->create();
$this->actingAs($user);
$request = new MyRequest();
$request->setContainer($this->app);
$attributes = ['aa' => 'asd'];
$request->initialize([], $attributes);
$this->app->instance('request', $request);
$authorized = $request->authorize();
$this->assertEquals(true, $authorized);
You should create some helper methods in base class to keep the tests DRY.
You need to have your form request class in the controller function, for example
public function store(MyRequest $request)
Now create HTML form and try to fill it with different values. If validation fails then you will get messages in session, if it succeeds then you get into the controller function.
When Unit testing then call the url and add the values for testing as array. Laravel doc says it can be done as
$response = $this->call($method, $uri, $parameters, $cookies, $files, $server, $content);
Here's a full example of testing validation:
use App\Http\Requests\PostRequest;
use Illuminate\Routing\Redirector;
use Illuminate\Validation\ValidationException;
class PostRequestTest extends TestCase
{
protected function newTestRequest($data = [])
{
$request = new PostRequest();
$request->initialize($data);
return $request
->setContainer($this->app)
->setRedirector($this->app->make(Redirector::class));
}
public function testValidationFailsWhenEmptyTitleIsGiven()
{
$this->expectException(ValidationException::class);
$this->newTestRequest(['title' => ''])->validateWhenResolved();
}
}

typo3 fe-manager how to get different admin emails

i have a question about fe-manager. In this extension it is possible to send a confirmation email to a admin. But it is always the same email. i like to send emails to various admins. for example: if the new user is from germany the receiving adress should be some#thing.de. if the new user is from switzerland the adress should be some#thing.ch.
any idea how to approach this?
any hints/solutions are more than welcome.
current state:
extension is created. i copied the finalCreate-Method from the AbstractController to my NewController. i changed the makeEmailArray() from:
Div::makeEmailArray(
$this->settings['new']['notifyAdmin'],
$this->settings['new']['email']['createAdminNotify']['receiver']['name']['value']
),
to:
Div::makeEmailArray('xxx#xxx.ch',
$this->settings['new']['email']['createAdminNotify']['receiver']['name']['value']
),
the ts setup.txt file is located in femanager_extended/Configuration/TypoScript/setup.txt
and contains the following code:
config.tx_extbase.objects {
In2\Femanager\Controller\NewController.className = Lbaumann\FemanagerExtended\Controller\NewController
}
is this the right approach?
There is no TypoScriptConfig for this behaiviour, but you can easily override the ControllerMethod and extend it with your needs.
Create your own extension like Vender "Vendor" (company/customername) and key "femanager_extended" with the extension_builder.
femanager_extended/Classes/Controller/NewController.php
<?php
namespace Vendor\FemanagerExtended\Controller;
class NewController extends \In2\Femanager\Controller\NewController
{
public function finalCreate($user, $action, $redirectByActionName, $login = true)
{
// own business logic
// replace the first Div::makeEmailArray...
// with your selected Admin-email-address
// see parent::finalCreate($user, $action, $redirectByActionName, $login);
}
}
femanager_extened/ext_typoscript_setup.txt
config.tx_extbase.objects {
In2\Femanager\Controller\NewController.className = Vendor\FemanagerExtended\Controller\NewController
}
I hope this will help you and i donĀ“t forgot any settings.

PHPUnit: Testing form submissions with session variables stored in Symfony2

I had a small test done in PHP for a Controller I had written in Symfony2:
class DepositControllerTest extends WebTestCase {
public function testDepositSucceeds() {
$this->crawler = self::$client->request(
'POST',
'/deposit',
array( "amount" => 23),
array(),
array()
);
$this->assertEquals(
"Deposit Confirmation",
$this->crawler->filter("title")->text());
}
}
Up to here, everything was great. Problem started when I realized I wanted to disable possible re-submissions while refreshing the page. So I added a small mechanism to send nonce on every submission.
It works something like this:
class ReplayManager {
public function getNonce() {
$uid = $this->getRandomUID();
$this->session->set("nonce", $uid);
return $uid;
}
public function checkNonce($cnonce) {
$nonce = $this->session->get("nonce");
if ($cnonce !== $nonce)
return false;
$this->session->set("nonce", null);
return true;
}
}
So I had to mofidy the controller to get the nonce when displaying the form, and consume it when submitting.
But now this introduces a problem. I cant make a request to POST /deposit because I dont know what nonce to send. I thought to requesting first GET /deposit to render the form, and setting one, to use it in the POST, but I suspect Symfony2 sessions are not working in PHPUnit.
How could I solve this issue? I would not want to go to Selenium tests, since they are significant slower, not to mention that I would have to rewrite A LOT of tests.
UPDATE: I add a very simplified version of the controller code by request.
class DepositController extends Controller{
public function formAction(Request $request){
$this->replayManager = $this->getReplayManager();
$context["nonce"] = $this->replayManager->getNonce();
return $this->renderTemplate("form.twig", $context);
}
protected function depositAction(){
$this->replayManager = $this->getReplayManager();
$nonce = $_POST["nonce"];
if (!$this->replayManager->checkNonce($nonce))
return $this->renderErrorTemplate("Nonce expired!");
deposit($_POST["amount"]);
return $this->renderTemplate('confirmation.twig');
}
protected function getSession() {
$session = $this->get('session');
$session->start();
return $session;
}
protected function getReplayManager() {
return new ReplayManager($this->getSession());
}
}
I'm not sure what ReplayManager does, but it looks to me as if it is not the right class to handle the 'nonce'. As the 'nonce' is ultimately stored in and retrieved from the session it should either be handled by the controller or abstracted out into its own class which is then passed in as a dependency. This will allow you to mock the nonce (sounds like a sitcom!) for testing.
In my experience problems in testing are actually problems with code design and should be considered a smell. In this case your problem stems from handling the nonce in the wrong place. A quick refactoring session should solve your testing problems.
It is possible to access the Symfony2 session from PHPUnit via the WebTestCase client. I think something like this should work:
public function testDepositSucceeds() {
$this->crawler = self::$client->request(
'GET',
'/deposit',
);
$session = $this->client->getContainer()->get('session');
$nonce = $session->get('nonce');
$this->crawler = self::$client->request(
'POST',
'/deposit',
array("amount" => 23, "nonce" => $nonce),
array(),
array()
);
$this->assertEquals(
"Deposit Confirmation",
$this->crawler->filter("title")->text());
}
EDIT:
Alternatively, if there is a problem getting the nonce value from the session, you could try replacing the two lines between the GET and POST requests above with:
$form = $crawler->selectButton('submit');
$nonce = $form->get('nonce')->getValue(); // replace 'nonce' with the actual name of the element

Drupal form error redirect

I need help for this problem:
In my Drupal 7 site i need to perform a redirect to a certain page if the login form is invalid, only in this occasion, and only for login form.
What is the best way to do this? what function is called?
Thanks in advance.
You have to use hook_form_alter and add or alter the #validate options. Prefer the second method:
function MYMODULE_form_alter(&$form, $form_state, $form_id) {
if ($form_id == 'user_login') {
$form['#validate'][] = 'MYMODULE_user_login_form_validate';
}
}
function MYMODULE_user_login_form_validate($form, &$form_state) {
// Do some validation here. Better take the same codes from the validation functions below.
if (...) {
drupal_goto('CUSTOM_PATH');
}
}
You can find the validation functions inside ROOT/modules/user/user.module file line 2113:
function user_login_default_validators() {
return array('user_login_name_validate', 'user_login_authenticate_validate', 'user_login_final_validate');
}
Similar questions:
(6.x, although it is the same) Drupal Modify Login System
https://drupal.stackexchange.com/questions/22952/custom-validation-for-a-form
using hook_user_login method you can achieve the same,
/**
* Implements hook_user_login();
*/
function MODULE_NAME_user_login(&$edit, $account) {
$url = 'PAGE_TO_BE REDIRECTED';
if (isset($user->uid) && $user->uid > 0) {
drupal_goto($url);
}
}