Jump to content

Need help with custom entities in admin


bonsaiko

Recommended Posts

Hello,

I developped a module that deals with custom entities that I created (PS 1.6). 

Everything is working fine except one small detail... 

I created the classes and admin controllers for my entities and I'm able to add / edit /delete records from the back office. 

When I go to an entity called "appellations", I can see the list of the "appellations" that were created and the number of "appellations". 

BUT when I do the same thing with another entity, called "plats", the number of plats is always "0". The difference between appellations and plats is that "plats" is a kind of hierarchical entity, which means one "plat" can have a parent. It's kind of like categories. So when I click on "plats" in admin, I don't see the list of all plats but instead all the plats that have id_parent = 0. 

This is working great except that the number displayed is "0" instead of the real number of the list that's dislayed. 

And then if I click on one element in my list, it displays ok all the "children" of this "plat", but still the number is 0. And I have no breadcrumb, which is the second issue that I have.

I really need some help of someone who is used to develop modules. I'm sure it's not a big issue, but I'm stuck.

I can display my code if needed.

Thanks a lot.

Link to comment
Share on other sites

Thanks a lot for your answer !

Here's my code, I will start with the code that's working ok, which deals with "appellation" entity, and then "plat" entity.

Here's the class for "appellation' :

<?php
if (!defined('_CAN_LOAD_FILES_') AND _PS_VERSION_ > '1.5')
    exit;

class Appellation extends ObjectModel
{
    public $id_appellation;
    public $nom_appellation;

    public static $definition = array(
        'table' => 'appellation',
        'primary' => 'id_appellation',
        'multishop' => true,
        'fields' => array(
            'nom_appellation' => array('type' => self::TYPE_STRING, 'validate'=> 'isGenericName', 'required' => true, 'size' => 200),
        )
    );

    public function __construct($id = NULL, $id_lang = NULL, $id_shop = null)
    {
        parent::__construct($id, $id_lang, $id_shop);
    }

    public function update($null_values = false)
    {
        return parent::update($null_values);
    }

    public function add($autodate = true, $null_values = false)
    {
        return parent::add();
    }

    public function delete()
    {
        return parent::delete();
    }
}

And here's the controller that goes with it :

<?php
include_once(_PS_MODULE_DIR_.'rbfilter/classes/Appellation.php');

class AdminAppellationController extends ModuleAdminController
{
    public function __construct()
    {
        // Set variables
        $this->table = 'appellation';
        $this->className = 'Appellation';

        // Call of the parent constructor method
        parent::__construct();

        $this->fields_list = array(
            'id_appellation' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25),
            'nom_appellation' => array('title' => $this->l('Label'), 'width' => 140),
        );

        $this->_defaultOrderBy = 'nom_appellation';
        $this->_defaultOrderWay = 'ASC';

        // Set fields form for form view
        $this->context = Context::getContext();
        $this->context->controller = $this;

        $this->addRowAction('edit');
        $this->addRowAction('delete');
        $this->bulk_actions = array(
            'delete' => array(
                'text' => $this->l('Delete selected'),
                'confirm' => $this->l('Would you like to delete the selected items?'),
            )
        );

        // Enable bootstrap
        $this->bootstrap = true;
    }

    public function initPageHeaderToolbar()
    {
        if (empty($this->display)){
            $this->page_header_toolbar_btn['new'] = array(
                'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token,
                'desc' => $this->l('Add New')
            );
        }

        parent::initPageHeaderToolbar();
    }

    public function renderForm()
    {
        if (!$this->loadObject(true))
            return;
        if (Validate::isLoadedObject($this->object))
            $this->display = 'edit';
        else
            $this->display = 'add';

        $id_appellation = Tools::getValue('id_appellation');
        $appellation = new Appellation($id_appellation, $this->context->language->id, $this->context->shop->id);

        $this->fields_form = array(
            'tinymce' => true,
            'legend' => array(
                'title' => $this->l('Add / edit appellation')
            ),
            'input' => array(
                array('type' => 'hidden', 'name' => 'id_appellation', 'default_value' => $appellation->id_appellation),
                array('type' => 'text', 'label' => $this->l('Appellation name'), 'name' => 'nom_appellation', 'size' => 30, 'required' => true, 'default_value' => $appellation->nom_appellation),
            ),
            'submit' => array('title' => $this->l('Save'))
        );

        return parent::renderForm();
    }

    public function postProcess()
    {
        if (Tools::isSubmit('submitAdd_appellation')) {
            $id_appellation = Tools::getValue('id_appellation');
            $appellation = new Appellation($id_appellation, $this->context->language->id, $this->context->shop->id);

            $appellation->nom_appellation = Tools::getValue('nom_appellation');

            if ($id_appellation > 0) {
                $appellation->update();
            }
            else {
                $save_value = $appellation->add();
                if(!$save_value)
                    $this->errors[] = Tools::displayError('Appellation could not be inserted. Please, check all again!');
                else
                    $this->success = Tools::displayError('Appellation added successfully.');
            }
        }
        elseif (Tools::isSubmit('delete_appellation')) {
            $appellation = new Appellation((int) Tools::getvalue('id_appellation'));
            $res = $appellation->delete();
            if (!$res) {
                $this->errors[] = Tools::displayError('Could not delete.');
            } else {
                $this->success = Tools::displayError('Appellation deleted successfully.');
            }
        }
    }
}

Once again everything is ok for appellation, it's working great in back office. 

Now with "plat' it's not working as I want. 

Here's the class

<?php
if (!defined('_CAN_LOAD_FILES_') AND _PS_VERSION_ > '1.5')
    exit;

class Plat extends ObjectModel
{
    public $id_plat;
    public $nom_plat;
    public $image_plat;
    public $id_parent;

    public static $definition = array(
        'table' => 'plat',
        'primary' => 'id_plat',
        'multishop' => true,
        'fields' => array(
            'nom_plat' => array('type' => self::TYPE_STRING, 'validate'=> 'isGenericName', 'required' => true, 'size' => 200),
            'id_parent' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'),
            'image_plat' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'),
        )
    );

    public function __construct($id = NULL, $id_lang = NULL, $id_shop = null)
    {
        parent::__construct($id, $id_lang, $id_shop);
    }

    public function update($null_values = false)
    {
        return parent::update($null_values);
    }

    public function add($autodate = true, $null_values = false)
    {
        return parent::add();
    }

    public function delete()
    {
        return parent::delete();
    }

    public static function getAllPlatsArray($null_option_value = false)
    {
        $reqSQL = 'SELECT id_kooki_plat, nom_plat FROM ' ._DB_PREFIX_ . 'kooki_plat';
        $plats = Db::getInstance()->executeS($reqSQL);
        if ($null_option_value) {
            $plats = array_merge(
                array(
                    0 => array(
                        'id_kooki_plat' => 0,
                        'nom_plat' => 'Aucun',
                    )
                ),
                $plats
            );
        }

        return $plats;
    }
}

I think the clas is ok. Now the controller, which must be not ok somewhere, but I don't know where :)

<?php
include_once(_PS_MODULE_DIR_.'rbfilter/classes/Plat.php');

class AdminPlatController extends ModuleAdminController
{
    protected $_plat = null;

    public function __construct()
    {
        // Set variables
        $this->table = 'plat';
        $this->className = 'KookiPlat';

        parent::__construct();

        $this->fields_list = array(
            'id_plat' => array('title' => $this->l('ID'), 'align' => 'center', 'width' => 25),
            'nom_plat' => array('title' => $this->l('Name'), 'width' => 140),
        );

        $this->_defaultOrderBy = 'nom_plat';
        $this->_defaultOrderWay = 'ASC';

        // Set fields form for form view
        $this->context = Context::getContext();
        $this->context->controller = $this;

        $this->bulk_actions = array(
            'delete' => array(
                'text' => $this->l('Delete selected'),
                'confirm' => $this->l('Would you like to delete the selected items?'),
            )
        );

        // Enable bootstrap
        $this->bootstrap = true;
    }

    public function initPageHeaderToolbar()
    {
        if (empty($this->display)){
            $this->page_header_toolbar_btn['new'] = array(
                'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token,
                'desc' => $this->l('Add New')
            );
        }

        parent::initPageHeaderToolbar();
    }

    public function init()
    {
        parent::init();

        if (($id_plat = Tools::getvalue('id_plat')) && $this->action != 'select_delete') {
            $this->_plat = new KookiPlat($id_plat);
        } else {
            if (Shop::getContext() == Shop::CONTEXT_SHOP) {
                $this->_plat = new KookiPlat();
            }
        }
    }

    public function initContent()
    {
        parent::initContent();
    }

    public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false)
    {
        $id_plat = (int)Tools::getvalue('id_plat');
        $reqSQL = "SELECT * FROM psrb_plat WHERE id_parent = $id_plat";
        $this->_list = Db::getInstance()->executeS($reqSQL);
    }

    public function renderList()
    {
        if (isset($this->_filter) && trim($this->_filter) == '') {
            $this->_filter = $this->original_filter;
        }

        $this->addRowAction('view');
        $this->addRowAction('add');
        $this->addRowAction('edit');
        $this->addRowAction('delete');

        return parent::renderList();
    }

    public function renderForm()
    {
        if (!$this->loadObject(true))
            return;
        if (Validate::isLoadedObject($this->object))
            $this->display = 'edit';
        else
            $this->display = 'add';

        $id_plat = (int)Tools::getValue('id_plat');
        $id_parent = (int)Tools::getValue('id_parent');
        $plat = new KookiPlat($id_plat, $this->context->language->id, $this->context->shop->id);
        $options = KookiPlat::getAllPlatsArray(true);

        $this->fields_form = array(
            'tinymce' => true,
            'legend' => array(
                'title' => $this->l('Add / edit plat')
            ),
            'input' => array(
                array('type' => 'hidden', 'name' => 'id_plat', 'default_value' => $plat->id_plat),
                array('type' => 'text', 'label' => $this->l('Label'), 'name' => 'nom_plat', 'size' => 30, 'required' => true, 'default_value' => $plat->nom_plat),
                array(
                    'type' => 'select',
                    'required' => true,
                    'label' => $this->l('Parent plat'),
                    'name' => 'plat_parent',
                    'options' => array(
                        'query' => $options,
                        'id' => 'id_plat',
                        'name' => 'nom_plat'
                    )
                ),
                array(
                    'type' => 'file',
                    'label' => $this->l('Picto'),
                    'name' => 'image_plat',
                    'thumb' => _PS_IMG_ . $plat->image_plat,
                    'default_value' => $plat->image_plat),
            ),
            'submit' => array('title' => $this->l('Save'))
        );

        // Valeurs par défaut
        if (isset($plat->id_parent))
            $this->fields_value['plat_parent'] = $plat->id_parent;
        else
            $this->fields_value['plat_parent'] = $id_parent;

        $this->tpl_vars['tinymce'] = true;
        $this->context->controller->addJS(_PS_JS_DIR_.'tiny_mce/tiny_mce.js');
        $this->context->controller->addJS(_PS_JS_DIR_.'admin/tinymce.inc.js');

        return parent::renderForm();
    }


    public function renderView()
    {
        $this->initToolbar();
        return $this->renderList();
    }

    public function initToolbar()
    {
        if (empty($this->display)) {
            $this->toolbar_btn['new'] = array(
                'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token,
                'desc' => $this->l('Add New')
            );
        }
        if (!Tools::isSubmit('id_plat')
            && ($this->display == 'view' || empty($this->display))) {
            $this->toolbar_btn['edit'] = array(
                'href' => self::$currentIndex.'&update'.$this->table.'&id_plat='.(int)$this->_plat->id.'&token='.$this->token,
                'desc' => $this->l('Edit')
            );
        }
        if (Tools::getValue('id_plat') && !Tools::isSubmit('updateplat')) {
            $this->toolbar_btn['edit'] = array(
                'href' => self::$currentIndex.'&update'.$this->table.'&id_plat='.(int)Tools::getValue('id_plat').'&token='.$this->token,
                'desc' => $this->l('Edit')
            );
        }

        if ($this->display == 'view') {
            $this->toolbar_btn['new'] = array(
                'href' => self::$currentIndex.'&add'.$this->table.'&id_parent='.(int)Tools::getValue('id_plat').'&token='.$this->token,
                'desc' => $this->l('Add New')
            );
        }
        parent::initToolbar();

        if (empty($this->display)) {
            $id_category = (Tools::isSubmit('id_category')) ? '&id_parent='.(int)Tools::getValue('id_category') : '';
            $this->toolbar_btn['new'] = array(
                'href' => self::$currentIndex.'&add'.$this->table.'&token='.$this->token.$id_category,
                'desc' => $this->l('Add New')
            );

            if (Tools::isSubmit('id_category')) {
                $back = Tools::safeOutput(Tools::getValue('back', ''));
                if (empty($back)) {
                    $back = self::$currentIndex.'&token='.$this->token;
                }
                $this->toolbar_btn['back'] = array(
                    'href' => $back,
                    'desc' => $this->l('Back to list')
                );
            }
        }
        if (!$this->lite_display && isset($this->toolbar_btn['back']['href']) //&& $this->_plat->level_depth > 1
            && $this->_plat->id_parent && $this->_plat->id_parent != 0) {
            $this->toolbar_btn['back']['href'] .= '&id_plat='.(int)$this->_plat->id_parent;
        }
    }

    public function postProcess()
    {
        $width = 150;
        $height = 200;
        if (Tools::isSubmit('submitAdd_plat')) {
            $id_plat = Tools::getValue('id_plat');
            $plat = new KookiPlat($id_plat, $this->context->language->id, $this->context->shop->id);

            // Nom du plat
            $plat->nom_plat = Tools::getValue('nom_plat');
            // Plat parent
            $plat->id_parent = Tools::getValue('plat_parent');

            // Picto du plat
            $type = Tools::strtolower(Tools::substr(strrchr($_FILES['image_plat']['name'], '.'), 1));
            $imagesize = @getimagesize($_FILES['image_plat']['tmp_name']);
            if (isset($_FILES['image_plat']) &&
                isset($_FILES['image_plat']['tmp_name']) &&
                !empty($_FILES['image_plat']['tmp_name']) &&
                !empty($imagesize) &&
                in_array(
                    Tools::strtolower(Tools::substr(strrchr($imagesize['mime'], '/'), 1)), array(
                        'jpg',
                        'gif',
                        'jpeg',
                        'png'
                    )
                ) &&
                in_array($type, array('jpg', 'gif', 'jpeg', 'png')) ) {
                $temp_name = tempnam(_PS_TMP_IMG_DIR_, 'PS');
                $salt = date('Y-m-d_H-i-s');
                $new_name = $plat->nom_plat;
                $new_name = KookiRBFilter::convert_to_slug($new_name);
                $new_name = $new_name . '_' . $salt . '.' . $type;

                if ($error = ImageManager::validateUpload($_FILES['image_plat']))
                    $errors[] = $error;
                elseif (!$temp_name || !move_uploaded_file($_FILES['image_plat']['tmp_name'], $temp_name))
                    return false;
                elseif (!ImageManager::resize($temp_name, _PS_IMG_DIR_ . $new_name, $width, $height, $type, true))
                    $errors[] = $this->displayError($this->l('An error occurred during the image upload process.'));
                if (isset($temp_name))
                    @unlink($temp_name);

                $plat->image_plat = $new_name;
            }

            if ($id_plat > 0) {
                $plat->update();
                Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&id_plat='.$id_plat.'&viewplat');
            }
            else {
                $save_value = $plat->add();
                if(!$save_value)
                    $this->errors[] = Tools::displayError('Plat could not be inserted. Please, check all again!');
                else {
                    $this->success = Tools::displayError('Plat added successfully.');
                }
            }
        }
        elseif (Tools::isSubmit('deleteplat')) {
            $plat = new KookiPlat((int) Tools::getvalue('id_plat'));
            $res = $plat->delete();
            if (!$res) {
                $this->errors[] = Tools::displayError('Could not delete.');
            } else {
                $this->success = Tools::displayError('Plat deleted successfully.');
            }
        }
    }
}

Like I explained I can see the list of plats that have no parent, it's ok, but the number displayed is "0 plat', while it's not true. 

And then when I click on one of the plats, i can see it's children, this part works fine also, but the number is still "o plat" and worse, I have no breacrumb which is very upsetting. I need to have breadcrumbs here or else the user doesn"t always knows where he is...

Thanks for your help !

Link to comment
Share on other sites

I would use a recursive function to get the children, I might have missed it in the code but it looks like you might be getting them all together. Get the root, then all its children, and so on, until the list of children is exhausted. SO if you have id = 0, get all of the ones with id_parent = 0, iterate, then get children for each. How you display them will change of course, I am not sure how the helper deals with it outside categories as I never used it.

Link to comment
Share on other sites

Hello Nemo,

Thanks for your answer :)

Actually I don't have any issue with getting the children because as I tried to explain, dirst I get the list of all entities with no parent, and it's working fine. 

Then when I click on one of them, it shows me its children, and so on. 

So everything is working fine. 

The only issue that I have is related to the breadcrumb and the total that's displayed.

As you can see I have more then one '"plat" and the number is not correct :

image.png.c0b6016e5ba11b0b83983f970339ab62.png

 

Other issue when I go down the children and grand-children, the breadcrumb doesn't appear so I never know where I am and I can't navigate (and the number is still 0). 

I'm just trying to recreate what happens with categories :

image.png.669f4ae2f8dac94d194d63a5b019e968.png

 

As you can see here I have a breadcrumb displayed (I don't know how to get this) which is useful to go up in the tree, and also the number is correct.

 

I hope it ios clearer now...

Thanks for your help !

 

Link to comment
Share on other sites

  • 1 month later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...