Prestashop custom tab in Back Office - prestashop

I'm developing a module for prestashop 1.5.3. I need to create a custom admin tab during the module installation. I make the install like this
public function install()
{
if( (parent::install() == false)||(!$this->_createTab()) )
return false;
return true;
}
And the _createTab method is:
private function _createTab()
{
$tab = new Tab();
$tab->id_parent = 7; // Modules tab
$tab->class_name='AdminWarranty';
$tab->module='fruitwarranty';
$tab->name[(int)(Configuration::get('PS_LANG_DEFAULT'))] = $this->l('Warranty');
$tab->active=1;
if(!$tab->save()) return false;
return true;
}
And nothing happens.. What am I doing wrong.. and where to find good prestashop developer reference.?

To create a custom tab for a module during installation you can use the following code.
Note: I am considering a test module called News.
private function _createTab()
{
/* define data array for the tab */
$data = array(
'id_tab' => '',
'id_parent' => 7,
'class_name' => 'AdminNews',
'module' => 'news',
'position' => 1, 'active' => 1
);
/* Insert the data to the tab table*/
$res = Db::getInstance()->insert('tab', $data);
//Get last insert id from db which will be the new tab id
$id_tab = Db::getInstance()->Insert_ID();
//Define tab multi language data
$data_lang = array(
'id_tab' => $id_tab,
'id_lang' => Configuration::get('PS_LANG_DEFAULT'),
'name' => 'News'
);
// Now insert the tab lang data
$res &= Db::getInstance()->insert('tab_lang', $data_lang);
return true;
} /* End of createTab*/
I hope the above code will help
Thanks

Well, I'm myself developing a PrestaShop module so in case someone lands here, the proper way.
For root tabs:
$rootTab = new Tab();
$rootTab->active = 1;
$rootTab->class_name = 'YourAdminControllerName';
$rootTab->name = array();
foreach (Language::getLanguages(true) as $lang) {
$rootTab->name[$lang['id_lang']] = $this->l("Root tab");
}
$rootTab->id_parent = 0; // No parent
$rootTab->module = $this->name;
$rootTab->add();
Note for version 1.5: When creating a root tab, the system will look for a YourAdminControllerName.gif in your module's folder as the tab icon. Also please note that root tabs don't work as links, despite them requiring a class_name.
For non-root tabs:
$tab = new Tab();
$tab->active = 1;
$tab->class_name = 'YourAdminControllerName';
$tab->name = array();
foreach (Language::getLanguages(true) as $lang) {
$tab->name[$lang['id_lang']] = $this->l("Non-root tab");
}
$tab->id_parent = $rootTab->id; // Set the root tab we just created as parent
$tab->module = $this->name;
$tab->add();
If you want to set an existing tab as parent, you can use the getIdFromClassName function. For example, in your case:
$tab->id_parent = (int)Tab::getIdFromClassName('AdminModules');
The add() function returns false if it fails, so you can use it in the if() as you were trying to do with the save() function.
Sadly PrestaShop is by far the worst documented CMS system I've had to work with, and the only way to really code for it is reading code, so I hope it helps someone.

Related

Copy cart into another cart in order to change the id_cart

I would like to give the cart object a new id, I have the following code:
if ($payment->order_result->return->failures->failure == 'field.ordernumber.exists') {
$dup = $this->context->cart->duplicate();
$this->context->cart->delete();
$this->context->cart = new Cart($dup['cart']->id);
}
The cart isn’t “replaced”, I tried several things: use the $GLOBALS of global keyword, but nothing really replaces or changes the cart object. What is the best approach?
Try with :
if ($payment->order_result->return->failures->failure == 'field.ordernumber.exists') {
$context = Context::getContext();
$cart_products = $context->cart->getProducts();
$this->context->cart->delete();
$newCart = new Cart();
if (!$context->cart->id) {
$guest = new Guest();
$context->cart->mobile_theme = $guest->mobile_theme;
$context->cart->add();
if ($context->cart->id)
$context->cookie->id_cart = (int)$context->cart->id;
}
foreach ($cart_products as $product) {
Db::getInstance()->insert('cart_product', array(
'id_product' => (int)$product->id,
'id_product_attribute' => (int)0,
'id_cart' => (int)$newCart->id,
'quantity' => (int)$product->quantity,
'date_add' => date('Y-m-d H:i:s')
));
}
}
Inspired by the answer of #ethercreation, I changed the following to solve my problem:
From
$dup = $this->context->cart->duplicate();
$this->context->cart->delete();
$this->context->cart = new Cart($dup['cart']->id);
To
$dup = $this->context->cart->duplicate();
$this->context->cart->delete();
$this->context->cookie->id_cart = $dup['cart']->id;
The essential part is $this->context->cart cannot be changed. The cart needs to be copied, then the current cart in the cookie should be changed. Therefore the cookie $this->context->cookie->id_cart should be changed to the id_cart of the newly created cart!

How to add a new link for my custom module page to the top horizontal menu in Prestashop 1.6.4

I created a module in which it will hook to one of the pages. But how to display the Link of my custom module to the top horizontal menu in Prestashop 1.6. i.e when I Navigate to Modules -> Modules and looking up for Top horizontal menu. and when I Click the Configure button to access the module configuration page how can I see my module link in the available Items lists. i.e see the image in the Available Items I want my custom link. Link of my custom module which i developed . i.e when my custom module is installed the link must appear here in the Available Items ,So that I can add my custom link the selected item
You have two choices:
create it by hand in the backoffice
In the blocktopmenu module configuration page you can create a new custom link under ADD A NEW LINK block. The link to your module will be /module/your_module_name/your_controller_name. Then you will be able to add this link to your menu under MENU TOP LINK.
create it programmatically
In the install method of your module you can create this custom link using blocktopmenu methods.
if (Module::isInstalled("blocktopmenu"))
{
// You will have to put the right path in here
require_once('../blocktopmenu/menutoplinks.class.php');
$languages = $this->context->controller->getLanguages();
$shops = Shop::getContextListShopID();
$links_label = array();
$labels = array();
foreach ($languages as $key => $val)
{
// You need to replace "my_module" and "my_controller" to get a link to your controller
$links_label[$val['id_lang']] = Context::getContext()->link->getModuleLink("my_module", "my_controller");
// Here set your link label for the menu
$labels[$val['id_lang']] = "My Link Name";
}
foreach ($shops as $shop_id)
{
$added = MenuTopLinks::add($links_label, $labels, 0, (int) $shop_id);
// You can check wether $added is true or false
}
}
create it programmatically with auto-suppression
public function install()
{
if (! parent::install())
{
return false;
}
if (Module::isInstalled("blocktopmenu"))
{
// You will have to put the right path in here
require_once('../blocktopmenu/menutoplinks.class.php');
$languages = $this->context->controller->getLanguages();
$shops = Shop::getContextListShopID();
foreach ($shops as $shop_id)
{
$links_label = array();
$labels = array();
foreach ($languages as $key => $val)
{
// You need to replace "my_module" and "my_controller" to get a link to your controller
$links_label[$val['id_lang']] = Context::getContext()->link->getModuleLink("my_module", "my_controller", array(), null, $val['id_lang'], $shop_id);
// Here set your link label for the menu
$labels[$val['id_lang']] = "My Link Name";
}
$added = MenuTopLinks::add($links_label, $labels, 0, (int) $shop_id);
if ($added) {
$link_id = Db::getInstance()->getValue("
SELECT DISTINCT id_linksmenutop
FROM `"._DB_PREFIX_."linksmenutop_lang`
WHERE link LIKE '" . $link . "'
AND id_shop LIKE '" . $shop_id . "'
");
Configuration::set("MY_MODULE_LINKS_TOP_" . $shop_id, $link_id);
}
}
}
}
public function uninstall()
{
if (! parent::uninstall())
{
return false;
}
if (Module::isInstalled("blocktopmenu"))
{
// You will have to put the right path in here
require_once('../blocktopmenu/menutoplinks.class.php');
$shops = Shop::getContextListShopID();
foreach ($shops as $shop_id)
{
$link_id = Configuration::get("MY_MODULE_LINKS_TOP_" . $shop_id);
if ($link_id !== false)
{
MenuTopLinks::remove($link_id, $shop_id);
}
}
}
}
Code no tested but must be working with Prestashop 1.6.

Yii2 signup without saving session data

I have registration form in my Yii2 advanced application. In my application only admin can register users. But when I register new user, admin session data are destroyed and new user's session data are set. What I am trying is not to change session data when I register new user. Admin user is still should be set to session data. How to solve this problem. This is my action in controller:
public function actionSignup()
{
$model = new SignupForm();
if(Yii::$app->user->can('admin'))
{
if (($response = self::ajaxValidate($model)) !== false)
return $response;
if (self::postValidate($model))
{
try
{
$trans = Yii::$app->db->beginTransaction();
if ($user = $model->signup()) {
Yii::$app->getUser()->login($user);
}
//tagidan tushgan odamining child_left, child_right tini o'zgartirish
$under = UserModel::findOne($user->id_parent_under);
if ($under->id_child_left == 0)
$under->id_child_left = $user->id;
else
$under->id_child_right = $user->id;
$under->update(false);
ChildrenBinaryModel::insertNewUser($user);
ChildrenClassicModel::insertNewUser($user);
$parents = ChildrenBinaryModel::find()->with('user')->where(["id_child" => $user->id])->orderBy(['depth' => SORT_ASC])->all();
$c_user = $user;
foreach($parents as $p)
{
$p_user = $p->user;
if ($p_user->id_child_left == $c_user->id)
$p_user->ball_left += 100;
else
$p_user->ball_right += 100;
$p_user->update(false);
$c_user = $p_user;
}
$trans->commit();
}
catch(\Exception $e)
{
$trans->rollBack();
return $this->renderContent($e->getMessage());
}
return $this->render('index');
}
return $this->render('signup', [
'model' => $model,
]);
}else{
throw new ForbiddenHttpException;
}
}
Checkout the documentation for \yii\web\User::login(). When this is run in your code by calling Yii::$app->getUser()->login($user), the session data is set to match your $user.
If it's always the admin user that's signing up new users, I'm not sure you even need to run the login method.
I have solved this problem. In order to make answer clearly and simple I will show you default signup action in site controller (Yii2 advanced template):
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
if (Yii::$app->user->enableSession = false &&
Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
return $this->render('signup', [
'model' => $model,
]);
}
Only I have done was adding this
Yii::$app->user->enableSession = false
inside the if statement

how to add an image to product in prestashop

i have a pragmatically added product in my code , the product is added to presta correctly but not about its image .
here is some part of my code that i used :
$url= "localhost\prestashop\admin7988\Hydrangeas.jpg" ;
$id_productt = $object->id;
$shops = Shop::getShops(true, null, true);
$image = new Image();
$image->id_product = $id_productt ;
$image->position = Image::getHighestPosition($id_productt) + 1 ;
$image->cover = true; // or false;echo($godyes[$dt][0]['image']);
if (($image->validateFields(false, true)) === true &&
($image->validateFieldsLang(false, true)) === true && $image->add())
{
$image->associateTo($shops);
if (! self::copyImg($id_productt, $image->id, $url, 'products', false))
{
$image->delete();
}
}
but my product have not any image yet
the problem is in copyImg method ...
here is my copyImg function :
function copyImg($id_entity, $id_image = null, $url, $entity = 'products')
{
$tmpfile = tempnam(_PS_TMP_IMG_DIR_, 'ps_import');
$watermark_types = explode(',', Configuration::get('WATERMARK_TYPES'));
switch ($entity)
{
default:
case 'products':
$image_obj = new Image($id_image);
$path = $image_obj->getPathForCreation();
break;
case 'categories':
$path = _PS_CAT_IMG_DIR_.(int)$id_entity;
break;
}
$url = str_replace(' ' , '%20', trim($url));
// Evaluate the memory required to resize the image: if it's too much, you can't resize it.
if (!ImageManager::checkImageMemoryLimit($url))
return false;
// 'file_exists' doesn't work on distant file, and getimagesize make the import slower.
// Just hide the warning, the traitment will be the same.
if (#copy($url, $tmpfile))
{
ImageManager::resize($tmpfile, $path.'.jpg');
$images_types = ImageType::getImagesTypes($entity);
foreach ($images_types as $image_type)
ImageManager::resize($tmpfile, $path.'-'.stripslashes($image_type['name']).'.jpg', $image_type['width'],
$image_type['height']);
if (in_array($image_type['id_image_type'], $watermark_types))
Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_entity));
}
else
{
unlink($tmpfile);
return false;
}
unlink($tmpfile);
return true;
}
can anybody help me ?
You have 2 issues:
You are passing 5th parameter (with value) to copyImg, while the function does not have such.
Your foreach ($images_types as $image_type) loop must include the Hook as well (add open/close curly braces).
foreach ($images_types as $image_type)
{
ImageManager::resize($tmpfile, $path.'-'.stripslashes($image_type['name']).'.jpg', $image_type['width'], $image_type['height']);
if (in_array($image_type['id_image_type'], $watermark_types))
Hook::exec('actionWatermark', array('id_image' => $id_image, 'id_product' => $id_entity));
}
You should also check if the product is imported correctly, expecially the "link_rewrite" and if the image is phisically uploaded in the /img/ folder.

Edit form with file input in zend framework 2

I use fielrenameupload validation and fileprg to upload file in my form .
It works very well but in edit action validation fails for file input
How I can solve this problem in edit action ?
this is edit action that works great for add action :
public function editAction()
{
$id = $this->params()->fromRoute('id',0);
$category = $this->categoryTable->get($id);
$form = $this->getServiceLocator()->get('CategoryForm');
$prg = $this->fileprg($form);
$form->bind($category);
if ($prg instanceof \Zend\Http\PhpEnviroment\Response)
{
return $prg;
}
elseif (is_array($prg))
{
if ($form->isValid())
{
$data = $form->getData();
$data['image'] = $data['image']['tmp_name'];
$category = new CategoryEntity;
$category->exchangeArray($data);
if ($this->categoryTable->save($category))
$this->redirect()->toRoute(null,array('action'=>'index'));
}
}
$view = new ViewModel(array(
'form' => $form,
));
$view->setTemplate('category/admin/add');
return $view;
}
And this is validation code for file input :
$image = new \Zend\InputFilter\FileInput('image');
$image->getFilterChain()->attachByName('filerenameupload',array(
'target' => 'data/upload/images/category',
'use_upload_name' => true,
'randomize' => true,
));
The add action passes the $form->isValid() validation because there is a image file posted in the form submit. However, in the edit action, it's empty.
In order to avoid avoid the problem you're facing try the following:
$imageFilter = $form->getInputFilter()->get( 'image' );
$imageFilter->setRequired( false );
Just be sure to place this lines before the $form->isValid() line.