Prestashop Controller - Change the current store on Multistore - php

I have a multistore environment on a prestashop. I created a module with a controller to change store if postal code is not correct. The problem comes when I use Tools::redirect($newUrlToRedirect); it redirects to my current store, and I need it redirects to another store. This is my code:
class cartportkeyDeriverModuleFrontController extends ModuleFrontController {
public function init(){
//I am in the url http://localhost/shopgroup/shopnameCART/quick-order and
//check the postal code, then clicking a link I go to the URL
//http://localhost/shopgroup/shopnameNEW/index.php?fc=module&module=cartportkey&controller=deriver&id_cart=XXX&id_shop=YYY
parent::init();
$id_cart = (int)Tools::getValue('id_cart');
$id_shop = (int)Tools::getValue('id_shop');
$this->context->cookie->id_cart = $id_cart;
$link_order = $this->context->link->getPageLink('order');
$testShop = Context::getContext()->shop;
//HERE I OBTAIN THE storeOLD instead storeNEW so I am redirecting again to storeOLD
$testShop = json_decode(json_encode($testShop), true);
$newUrlToRedirect = "http://".$testShop['domain'].$testShop['physical_uri'].$testShop['virtual_uri'].'quick-order';
//print $newUrlToRedirect;
$cart = new Cart(33);
$cart->delete();
Tools::redirect($newUrlToRedirect);
}
public function initContent() {
parent::initContent();
}
}
I had put some clarifications in the code as comments. The question is, how can I change the active store??

I have found my own answer. Instead of getting the context in $testShop = Context::getContext()->shop;
Change that line for:
$testShop = new Shop($id_shop);
$testShop->getContext();
Everything fine. Thanks!

Related

front controller won't load css and js from setMedia on a prestashop 1.7 module

I'm writing a prestashop module for prestashop 1.7.2.1.
I created a front controller for my module with the following code:
<?php
require_once (__DIR__.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'php'.
DIRECTORY_SEPARATOR.'TuxInDb.php');
class TuxInModCarTypeCarTypeProductsModuleFrontController extends ModuleFrontController {
private $tuxDb;
public function initContent(){
parent::initContent();
$productIds = [];
$this->tuxDb = TuxInDb::getInstance();
$companyName = Tools::getValue('company_name');
$modelName = Tools::getValue('model_name');
$year = Tools::getValue('year');
$month = Tools::getValue('month');
$carType = Tools::getValue('car_type');
$carListCarTypeIds=$this->tuxDb->getCarListCarTypeIds($companyName,$modelName,$carType,$year,$month);
$productIds = $this->tuxDb->getProductIdsByCarListCarTypeIds($carListCarTypeIds);
$this->context->smarty->assign('product_ids',$productIds);
$this->setTemplate('module:tuxinmodcartype/views/templates/front/cartypeproducts.tpl');
}
public function setMedia() {
parent::setMedia();
$this->registerStylesheet('module-tuxinmodcartype-cartypeproducts-style','modules/'.$this->module->name.'/css/cartypeproducts.css');
$this->registerJavascript('module-tuxinmodcartype-cartypeproducts-js','modules/'.$this->module->name.'/js/cartypeproducts.js');
}
}
as you can see in setMedia() function I load a css and js files.
I even debugged it in xdebug and I noticed that those lines of code actually get executed, but when I try to browse my front controller with the following url:
http://prestashop.dev:8080/index.php?company_name=BMW&model_name=SERIA+1&year=2011&month=1&car_type=5+%D7%93%D7%9C%D7%AA%D7%95%D7%AA+%28%D7%94%D7%90%D7%A6%D7%B3%D7%91%D7%A7%29&fc=module&module=tuxinmodcartype&controller=cartypeproducts&id_lang=1
and I check the network tab of my google chrome browser I noticed that the js and css file I required do not get loaded.
any ideas?
I see no javascript errors or php errors (I also have DEV enabled in prestashop).
If an asset path is wrong then Prestashop won't even append it to the browser's <head> (or bottom depending on CCC settings) and won't throw out any errors.
Probably your path is incorrect, to get proper path use this:
$this->registerStylesheet('module-tuxinmodcartype-cartypeproducts-style', $this->module->getPathUri() . 'css/cartypeproducts.css');
$this->registerJavascript('module-tuxinmodcartype-cartypeproducts-js', $this->module->getPathUri() . 'js/cartypeproducts.js');
This works well with PrestaShop 1.7.x
Add this inside your ModuleFrontController:
public function setMedia()
{
parent::setMedia();
$this->addCSS($this->module->getPathUri().'views/css/style.css');
}
I hope this helps!

SilverStripe 3.1+ Using PHP to dynamically change the URL slug of a Redirector

This is an extension of my original question SilverStripe 3.1+ Dynamically creating page redirects
I have a product page URL
a) www.mysite.com/category/subcat/productid
You can visit this page via a a separate redirector page
b) www.mysite.com/productid
Page 'a' has tabs which can be visited via
c) www.mysite.com/category/subcat/productid/tabid
I would like to use PHP to dynamically create links / redirectors for each product page create so it can be visited by:
1) A short URL using only its 'predicted' shown in 'b' (I can do this by creating a page redirector but this is long winded for a large number of products.
2) Create a short URL for each tab link as well, so 'c' would be redirected from: d) www.mysite.com/productid/tabid
The 'tabid' can be hard coded and in my case would be: audio, videos, pictures, firmware
Currently using the code in my ProductPage.php
class ProductPage_Controller extends Page_Controller {
private static $allowed_actions = array(
'audio',
'pictures',
'firmware',
'videos',
);
public function audio() {
$this->redirect($this->Link().'?tab=audio');
}
public function pictures() {
$this->redirect($this->Link().'?tab=pictures');
}
public function firmware() {
$this->redirect($this->Link().'?tab=firmware');
}
public function videos() {
$this->redirect($this->Link().'?tab=videos');
}
Allows me to go from /video to /?tab=video but this of course does not shorten the URL which is the final result I'm after.
Possibly this could be done in an extension of the RedirectorPage.php?
One way to do this is to use onBeforeHTTPError404 to hook into when a 404 error is called and to redirect any product found.
We create a ProductRedirectExtension with an onBeforeHTTPError404 function. This function will get called when a page cannot be found, but before the system returns a 404 error. The code in here will check if a ProductPage exists with a URLSegment with the first part of user's URL string. If a ProductPage is found we then check if the second part of the user's URL string is one of the tab keywords. After that the user is redirected to the page.
ProductRedirectExtension.php
class ProductRedirectExtension extends Extension {
public function onBeforeHTTPError404( $request ) {
$urlSegment = $request->param('URLSegment');
$action = strtolower($request->param('Action'));
$page = ProductPage::get()->filter('URLSegment', $urlSegment)->first();
if ($page) {
$link = $page->Link();
if ($action == 'audio' || $action == 'pictures' || $action == 'firmware' || $action == 'videos') {
$link .= '?tab=' . $action;
}
$response = new SS_HTTPResponse();
$response->redirect($link, 301);
throw new SS_HTTPResponse_Exception($response);
}
}
}
We enable this extension with the following config settings.
config.yml
RequestHandler:
extensions:
- ProductRedirectExtension
ContentController:
extensions:
- ProductRedirectExtension
ModelAsController:
extensions:
- ProductRedirectExtension
The shortest you could go is www.mysite.com/product/productid/tabid. It is possible to do this without the product part, but this would make your life a lot harder as you would have to go through a lot of trouble to still have access to Admin and Dev for example.
If you want the shortest URL you should make a new Page, as your current ProductPage is a child of another page, telling from your URL:
www.mysite.com/category/subcat/productid
You can achieve the best scenario with this code:
class ProductRedirectPage_Controller extends Page_Controller
{
private static $allowed_actions = [
'Product'
];
private static $url_handlers = [
'$ID/$TabID' => 'Product'
];
public function Product()
{
// Get your ProductPage, this should work if there is only one ProductPage
$page = ProductPage::get()->first();
if(! $productId = $this->request->param('ID'))
return $this->redirect($page->Link()); // or send them somewhere else
$tabId = $this->request->param('TabID');
$link = $page->Link('yourAction/' . $productId . '/' . $tabId);
return $this->redirect($link);
}
}
EDIT
With this code, when www.mysite.com/product/productid/tabid is visited, it will redirect you to where your ProductPage is. Maybe you wish to change the /$tabId to ?tabId=' . $tabId, but that is totally up to you.
So if I'm to summarise, you want newpage/video to open the correct on page tab, rather than being an action to render a different page?
You could do something funky with private static $url_handlers, to set a parameter you could query through $request->param('Thing').
Or you could set up handleAction to test whether or not $action either is one of the things in the list (and set flags for later use in eg. a template), or otherwise parent::handleAction.
This answer isn't extremely fleshed out, but should hopefully provide you some ideas on directions to investigate for your own use case.

How set module view for custom searcher in prestashop 1.6

I'm trying to integrate Fotolia Api with Prestashop 1.6.0.9.
I already make module with custom tab, but I have no idea how set view from module folder for this tab. Sorry to say, but "documentation for developers" SUCKS.
I can't find any working solution.
public function install() {
if (!parent::install()
|| !$this->registerHook('backOfficeHeader')
|| !$this->registerHook('header')
) return false;
$tab = new Tab();
$tab->class_name = 'AdminFotoliaSelector';
$tab->id_parent = 0;
$tab->module = $this->name;
$tab->name[(int)(Configuration::get('PS_LANG_DEFAULT'))] = 'Fotolia Selector';
$tab->add();
return true;
}
I had big problem with make proper controller, and now I just can't load anything/ I have no idea how do this.
<?php
if (!defined('_PS_VERSION_'))
exit;
class AdminFotoliaSelectorController extends ModuleAdminController {
public $name;
public function __construct() {
$this->lang = (!isset($this->context->cookie) || !is_object($this->context->cookie)) ? intval(Configuration::get('PS_LANG_DEFAULT')) : intval($this->context->cookie->id_lang);
parent::__construct();
}
public function initContent() {
parent::initContent();
$this->renderForm();
}
public function renderForm() {
$path = _MODULE_DIR_."fotoliaselector";
$more = $this->module->display($path, 'views/templates/admin/fotoliaselector.tpl');
return $more.parent::renderForm();
}
When I try die($more) it gives me content of .tpl, anyway when I click tab in back office it's still empty.
I have debug options on, compiling on, cache off.
So just enlight me please, how am I supose to show ANYTHING there?
I think the problem is that you don't display tab's content at all.
I don't know what module->display method does, but I think you should change in initContent() method line:
$this->renderForm();
into
echo $this->renderForm();
If it won't help you should look at this documentation and try to do it without external classes - only try to use Smarty to display simple content without using Tab class or AdminFotoliaSelector
Well i know it will sounds weird but you need to take some similar modules, and read his code and will see some methods names are the same in each module.
Then copy that, install and play with some changes etc.
Imho you miss standard method getContent() form where you need to pass some data for smarty:
public function getContent()
{
global $smarty, $cookie;
......
//some code
......
$this->_html .= '<script type="text/javascript" src="'.__PS_BASE_URI__.'js/tinymce/jscripts/tiny_mce/tiny_mce.js"></script>';
$this->_html .= '<h1>My module title or stuff</h1>';
$this->_html .= $this->getMyCoolFormOrConfig();
$smarty->assign('errors', $this->errors);
$smarty->assign('message', $this->message);
$this->_html .= $this->display(__FILE__, 'name_of_tpl_file.tpl');
return $this->_html;
}
to simple add tab in BackOffice code like this:
$id_tab=Tab::getIdFromClassName('AdminPayment');
$newtab=new Tab();
$newtab->id_parent=$id_tab;
$newtab->module=$this->name;
$newtab->class_name='MyClassName'; //will be same like MyClassName.php in folder of you module where you need to create you class and extend the AdminTab and from there with function you need to echo you name module
$newtab->position=Tab::getNbTabs($id_tab)+1;
$newtab->name[$cookie->id_lang]=$this->l("Name of you stuff");
$newtab->name[Configuration::get('PS_LANG_DEFAULT')]=$this->l("Name of you stuff");
$newtab->add();
Study this file there /controllers/admin/AdminModulesController.php
and you see what methods are using in each module
Take a look greater feature to generate you module structure (register requeired) https://validator.prestashop.com/generator

How To Use MVC PHP With Case Sensitive?

I am creating website in PHP. I am using MVC in PHP. My website works like this, if user go to example.com/about then it it will load About class and index() function. If user will go to localhost/about/founder then it will load founder() function from About class. but the thing is that if I go to localhost/About or localhost/AbOut or anything like that it is loading default index() function from About class file. So what to do with case sensitivity? I mean I want my script to load index() function from class file if it is localhost/about or localhost/terms. If anything is in uppercase, then it should load 404 error function. 404 error function is already set in my site.
Please help me friends.
here is my Bootstrap.php class file
<?php
/*
Bootstrap class to run functions by URL
*/
class Bootstrap {
public $_req;
public $_body;
public $_file;
public $_error;
function __construct(){
if(empty($_GET['req'])){
require 'classes/home.php';
$this->_body = new Home();
$this->hdr($this->_body->head());
$this->_body->index();
$this->ftr();
exit();
}
$this->_req = rtrim($_GET['req'], '/');
$this->_req = explode('/', $this->_req );
$_file = 'classes/'.$this->_req[0].'.php';
if(file_exists($_file)){
require $_file;
}
else {
$this->error(404);
}
$this->_body = new $this->_req[0];
$this->hdr($this->_body->head());
if(isset($this->_req[2])){
if(method_exists($this->_req[0], $this->_req[1])){
$this->_body->{$this->_req[1]}($this->_req[2]);
}else {
$this->error(404);
}
}else {
if(isset($this->_req[1])){
if(method_exists($this->_req[0], $this->_req[1])){
$this->_body->{$this->_req[1]}();
}else {
$this->error(404);
}
}else {
$this->_body->index();
}
$this->ftr();
}
}
//this function is to set header in html code
public function hdr($var = false){
echo '<!DOCTYPE HTML><html><head>'.$var.'</head><body>';
}
//this function is tp set footer in html code
public function ftr($var = false){
echo $var.'</body></html>';
}
//error handler
public function error($var){
require 'classes/er_pg.php';
$this->_error = new Error();
$this->_error->index($var);
}
}
You shouldn't use anything to load non-lowercase URLs because of the duplicate content, and that's a good thing you're doing. The wrong URLs should fail automatically in such cases.
However, since you didn't show how are you making those calls, then only thing I can suggest at this point is to check if the called method exists (case-sensitive), and if not, throw/redirect to a 404 page (header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");).
UPDATE
After all the chat in the comments, seems like file_exists is not case-sensitive in your case, which is really weird. Hopefully someone will be able to figure it out so I can delete this (keeping it because of the info in the comments).
I solved the problem. I used this
if(ctype_lower($this->_req[0])){
$_file = 'classes/'.$this->_req[0].'.php';
and now its working. Thanx anyways friends.

Joomla not display view for task

I have component called mycomponent
models
paypal.php
controllers
paypal.php
views
paypal
view.html.php
index.html
tmpl(folder)
default.php
index.html
In controller i have this code
<?php
// No direct access.
defined('_JEXEC') or die;
jimport('joomla.application.component.controlleradmin');
/**
* Objectdefects list controller class.
*/
class MycomponentControllerPaypal extends JControllerAdmin
{
public function paypaldetails()
{
$model = $this->getModel('paypal');
// Get token
$token = urlencode(htmlspecialchars(JRequest::getVar('token')));
if (!$token)
{
// Missing $token parameter
$app = JFactory::getApplication();
$app->enqueueMessage(JText::_('COM_INSTALLER_MSG_MISSING_TOKEN'));
}
else
{
// Install plugin
$model->paypaldetails($token);
}
}
}
In model i have this fragment of code
public function paypaldetails($token){
$environment= $this->environment;
// Add request-specific fields to the request string.
$nvpStr = "&TOKEN=$token";
// Execute the API operation; see the PPHttpPost function above.
$httpParsedResponseAr = $this->PPHttpPost('GetExpressCheckoutDetails', $nvpStr);
//var_dump($httpParsedResponseAr);
if("SUCCESS" == strtoupper($httpParsedResponseAr["ACK"]) || "SUCCESSWITHWARNING" == strtoupper($httpParsedResponseAr["ACK"])) {
$paypaldetails=array();
$paypaldetails["firstname"]= $httpParsedResponseAr['FIRSTNAME'];
$paypaldetails["lastname"] = $httpParsedResponseAr["LASTNAME"];
$paypaldetails["countrycode"] = $httpParsedResponseAr["COUNTRYCODE"];
$this->paypaldetails=$paypaldetails;
$a=$this->paypaldetails;
var_dump($a);
} else {
exit('GetExpressCheckoutDetails failed: ' . print_r($httpParsedResponseAr, true));
}
}
In view/template/default.php i have this
<?php
// no direct access
defined('_JEXEC') or die;
// Import CSS
$document = JFactory::getDocument();
$document->addStyleSheet('components/com_mycomponent/assets/css/defects.css');
$results = $this->items;
var_dump($results);
echo 'Firstname: '.$results[firstname];
echo '<br>Lastname: '.$results[lastname];
echo '<br>Countrycode: '.$results[countrycode];
When i run this url index.php?option=com_fewostar&view=paypal&task=paypal.paypaldetails&token=EC-92L7275685367793U&PayerID=TGWAUKNJLH2WL
I view first var_dump($a); located on model, but second var_dump($results); located in views/paypal/tmpl/default.php not display, and field in view not display. for any reason this url not call view. When i run this url index.php?option=com_fewostar&view=paypal code without task, view is display. but for this url
index.php?option=com_fewostar&view=paypal&task=paypal.paypaldetails&token=EC-92L7275685367793U&PayerID=TGWAUKNJLH2WL no display view. How i call view for this task, may be i need other view file, different of default.php?
I see a couple of problems here.
First, the code is not exactly using Joomla MVC style (even if it works for you, might be harder for people familiar with Joomla to debug).
Model method should be called getPaypaldetails and return something
public function getPaypaldetails()
{
// For Joomla 1.7+ use JInput instead of JRequest (deprecated)
$token = JFactory::getApplication()->input->getVar('token');
// some code
return $paypaldetails;
}
view.html.php should and get and data from model and assign to itself
public function display($tpl = null)
{
// Get some data from the models
$items = $this->model->get('paypaldetails');
// If data are incorrect, show nice error message
// ...
$this->items = $items;
}
View Layout file should be placed in /com_fewostar/views/paypal/tmpl/default.php
By default, the view is only called by the "display" task (which is the default task). Since you use your own task, you need to either redirect to the view after your task is finished or try to load the display function at the end.

Categories