I am trying to build a module for Prestashop 1.6 that would redirect the user if the targeted URL is present in a database.
What I'm going to do is the following:
public function checkRedirection ($url) {
$line = Db::getInstance()->executeS('SELECT * FROM ps_custom_redirection WHERE url = ' . pSQL($url));
if (!sizeof($line)) {
return null;
}
header('Location: ' . $line[0]['destination']);
http_response_code($line[0]['http_code']);
exit();
}
Now, I could run this function when the displayTop hook is fired. But I would rather launch this function at the beginning of the request's process.
Does Prestashop provide such a hook? If not, can I create one? Where should I write the code to fire it?
The fist hook executed is actionDispatcher – you can use it if you want.
You'll find this hook executed in /classes/Dispatcher.php. Search for the code Hook::exec('actionDispatcher', $params_hook_action_dispatcher);.
If you want to add this hook to your module, you need to use its name in the main module file like this:
public function install() {
return parent::install()
&& $this->registerHook('actionDispatcher');
}
public function hookActionDispatcher($params) {
// your code
Tools::redirect($url);
}
In Prestashop Tools::redirect($url); is used if redirecting.
Related
Goodmorning everyone,
I'm developing a module for prestashop 1.7, at the moment I'm having problems intercepting the postprocess method in the main class of my module.
I need to do the checks on submit the form (which are on the user profile page, where I set personal information).
From what I understand, in a form a submit is made, the first thing that is called in a class is precisely the postProcess () method that takes care of validating the data received from the form just submissive (correct me if I'm wrong).
The problem is that when I submit my form it does not enter the postPorcess () method (I checked for a die ("test") and it does not even show the latter), while if I do the check I need by invoking my method staff inside a hook is made,
Can you tell me where I'm wrong?
Thank you very much and have a nice day.
Daniel.
Daniel,
This might be an endpoint problem, however, if you are sure to just handle the request via this Class, just use Tools::getValue('something_in_form') / Tools::isSubmit('var') to check that it's sent.
You don't really need to apply this one. If you need example, you should check Prestashop's native modules or Admin controllers, as it depends a lot of where you need to do this.
My thought after some years of module dev is that you should use a module front controller endpoint as you would with an API and a do a response in JSON like this example :
<?php
class DummyModuleNameAjaxModuleFrontController extends ModuleFrontController
{
public function initContent()
{
$response = array();
require_once _PS_MODULE_DIR_.'dummymodulename/dummymodulename.php';
$mod = new dummymodulename;
if (Tools::isSubmit('action') && Tools::isSubmit('var') && Tools::getValue('var') == $mod->getSomethingForSecurity()) {
$context = Context::getContext();
$cart = $context->cart;
switch (Tools::getValue('action')) {
case 'dummy_action_name':
// Don't forget to type it with an INT or secure this entry with strip_tags
$my_var = Tools::getValue('var');
break;
default:
break;
}
}
echo Tools::jsonEncode($response);
die;
}
}
How to upload a file in symfony 4.I have done with the symfony document. I don't know where I have missed something. Its throws error while uploading file give me some clues
REFERED LINK:
https://symfony.com/doc/current/controller/upload_file.html
ERROR:
The file "" does not exist
Entity
public function getBrochure()
{
return $this->brochure;
}
public function setBrochure($brochure)
{
$this->brochure = $brochure;
return $this;
}
File upload Listener
class FileUploader
{
private $targetDirectory;
public function __construct($targetDirectory)
{
$this->targetDirectory = $targetDirectory;
}
public function upload(UploadedFile $file)
{
$fileName = md5(uniqid()).'.'.$file->guessExtension();
$file->move($this->getTargetDirectory(), $fileName);
return $fileName;
}
public function getTargetDirectory()
{
return $this->targetDirectory;
}
}
This Symfony tutorial works fine for me so I'll try to explain how and perhaps it will help you or people still looking for an answer, this post getting a bit old.
So first you have to create the FileUploader service in App\Service for better reusability (chapter: Creating an Uploader Service). You can basically copy/paste what they've done here, it works like a charm. Then you need to open your services.yaml in Config folder and explicit your brochure directory:
parameters:
brochures_directory: '%kernel.project_dir%/public/uploads/brochures'
# ...
services:
# ...
App\Service\FileUploader:
arguments:
$targetDirectory: '%brochures_directory%'
Now everything is normally ready to use your FileUploader service.
So if you're in your controller (for example), I guess you want to use it in a form. Thus, you just have to do this (don't forget to use your Service in your Controller):
public function myController(FileUploader $fileUploader)
{
// Create your form and handle it
if ($form isValid() && &form isSubmitted()) {
$file = $myEntity->getBrochure();
$fileName = $this->fileUploader->upload($file);
$myEntity->setBrochure($fileName);
// Form validation and redirection
}
// Render your template
}
One important point I forgot to say. In your FormType, you need to say that the Brochure will be a FileType:
$builder->add('brochure', FileType::class)
But in your entity you have to specify your brochure is stored as a "string":
/**
* #MongoDB\Field(type="string")
*/
protected $brochure;
The reason is your file is getting uploaded and saved in your public/uploads/brochure. But your database is only remembering a string path to reach it.
I hope this will help!
I am trying to add javascript file in prestashop admin using backOfficeHeader hook using a module but nothing happened. My code is given below.
public function install()
{
if (!parent::install()
|| !$this->registerHook('backOfficeHeader'))
return false;
return parent::install() &&
$this->registerHook('backOfficeHeader');
}
public function hookBackOfficeHeader() {
$this->context->controller->addJS(_MODULE_DIR_.$this->module->name.'js/hs_custom.js');
}
If you are using PS 1.5 or 1.6 you should use hook "actionAdminControllerSetMedia".
Your module installer should check which prestashop version is used and then register the needed hook.
if (version_compare(substr(_PS_VERSION_, 0, 3), '1.5', '<'))
$this->registerHook('BackOfficeHeader');
else
$this->registerHook('actionAdminControllerSetMedia');
Then you need to addJS on each hook in its version format:
PS>=1.5
public function hookActionAdminControllerSetMedia($params) {
$this->context->controller->addJS($this->_path.'views/js/hs_custom.js');
}
PS<=1.4
public function hookBackOfficeHeader($params) {
Tools::addJS($this->_path.'views/js/hs_custom.js');
}
did u try to check addJS path? I think nothing more can be possible if other JS files working.
Try to use $this->_path.
$this->context->controller->addJS($this->_path.'views/js/hs_custom.js');
1) Output path and check if it is valid.
2) Reload page and check network. Page load your script or not?
3) Remember to reset module if u change something with hooks.
4) Check module hooks.
You did several mistakes.
This is the invalid access to the property: $this->module->name. Must be $this->name. I.e., the correct code to generate a path to JavaScript file is:
_MODULE_DIR_ . $this->name . '/js/hs_custom.js'
Or like this (shorted):
$this->_path . 'js/hs_custom.js'
You are also did the double installation of the module and of the hook.
You can use the hook BackOfficeHeader, but the hook ActionAdminControllerSetMedia is preferred.
So, the correct example to add a JS and a CSS files for a back-office (i.e. for AdminController) via a module class is:
public function hookActionAdminControllerSetMedia($params)
{
// Adds your's CSS file from a module's directory
$this->context->controller->addCSS($this->_path . 'views/css/example.css');
// Adds your's JavaScript file from a module's directory
$this->context->controller->addJS($this->_path . 'views/js/example.js');
}
Here is the detailed information, how to register JavaScript in a back-office (in admin pages).
I also met this problem, there is no error and warning, all grammar is right. But cannot find my js File.
I found the reason finally. In my case there is nothing in JS file and system passes this file which has no content always.
For me "this->_path" dosn't work. My solution is to use $_SERVER['DOCUMENT_ROOT']
public function hookActionAdminControllerSetMedia($params)
{
// add necessary javascript to products back office
if($this->context->controller->controller_name == 'AdminProducts' && Tools::getValue('id_product'))
{
$this->context->controller->addJS($_SERVER['DOCUMENT_ROOT']."/modules/apl/views/js/jquery.ui.touch-punch.min.js");
}
}
I have a module and I want to display the "blocknewproducts" inside of it. What is the best option?
Thanks!
Ok, we lack some more info but i will share a way to do it in Prestashop 1.6.x:
Your module :
Given you have a custom hook named displayMyModule in your module install method :
public function install() {
if (!parent::install() || !$this->registerHook('displayMyModule')) {
return false;
} else {
return true;
}
}
Now, where you want to display the content of this hook is up to you. For example if it's on a category page, in category.tpl you add
{hook::exec('displayMyModule')}
Block new Products
Now to display the blocknewproducts we will create an override of this core module and register the displayMyModule hook :
in /override/modules/blocknewproducts/blocknewproducts.php :
if (!defined('_PS_VERSION_'))
exit;
class BlockNewProductsOverride extends BlockNewProducts
{
public function install()
{
$success = (parent::install()
&& $this->registerHook('displayMyModule'));
return $success;
}
public function hookDisplayMyModule($params)
{
return $this->hookRightColumn($params);
}
}
In hookDisplayMyModule we simply return the hookRightColumn method to not rewrite code.
Don't forget to go into back-office/modules and reinitialize blocknewproducts module
And that's about it... but keep in mind that you could also just override the blocknewproducts module to register hooks that already exist like shown above.
TLDR: Maybe you don't need a module if you just want to show block new products elsewhere.
What I know to do:
1) Create a module controller that allows translation.
I can declare texts to translate either in the controller itself or in the template:
/modules/mymodule/controllers/front/list.php
class myModuleListModuleFrontController extends ModuleFrontController
{
public function initContent()
{
parent::initContent();
$this->l('Some text to translater');
$this->setTemplate('list.tpl');
}
}
/modules/mymodule/views/templates/front/list.tpl
{l s='Some other text' mod='mymodule'}
2) I know to create some output that is not embedded in html, like for instance some json object:
/modules/mymodule/json.php
include( '../../config/config.inc.php' );
echo json_encode(array('key' => 'Some text'));
What I need:
I need to be able to translate some text AND have the output sent to the browser without the surrounding html. I have to be able to do one of those:
use a standalone file and be able to declare text to translate, similar to this (does not work):
include( '../../config/config.inc.php' );
echo json_encode(array('key' => l('Some text')));
use a module controller and force raw output, similar to this (does not work either):
class myModuleListModuleFrontController extends ModuleFrontController
{
public function initContent()
{
parent::initContent();
$this->noHtml = true;
echo json_encode(array('key' => l('Some text')));
}
}
If you want to translate text in FrontController, you can only do it in two ways:
Translate the texts inside a template
// Inside module front controller
$template = '.../template.tpl'
$this->context->smarty->fetch($template)
// Inside template.tpl
{l s='Translateable text' mod='mymodule'}
Or use strings already translated inside main module file
// Inside module front controller
$this->module->l('My string');
// But it has to already exist inside mymodule.php
$this->l('My string'); // You don't have to use it, it just has to exist to get scanned by RegEx.
If you want to return something back to Ajax request in your module front controller
public function init() {
parent::init(); // If you need to
// Some code here
if (Tools::getValue('ajax'))
{
header('Content-Type: text/html');
die($this->context->smarty->fetch($template));
// Or
header('Content-Type: application/json');
die(Tools::jsonEncode($response_array));
}
There is also a function called
FrontControllerCore::getLayout # Line 1209
Which you can use to override the whole page template, however, it should be used to create unique display for products and other page (like full screen product presentation, etc.)
If you want to ouput a file yourself while not providing a full file path to the user:
public function init() {
parent::init(); // If you need to
if (ob_get_level() && ob_get_length() > 0)
ob_end_clean();
// Set download headers
header('Content-Transfer-Encoding: binary');
header('Content-Type: '.$mime_type);
header('Content-Length: '.filesize($file));
header('Content-Disposition: attachment; filename="'.$filename.'"');
// Prevents max execution timeout, when reading large files
set_time_limit(0);
$fp = fopen($file, 'rb');
while (!feof($fp))
echo fgets($fp, 16384);
exit;
Apart from that, I don't image what else would tou possibly need to build your app. Always send token to your controllers for security!