4
votes

I have created a component in joomla 2.5 that creates a new article and adds that article to a menu item.

Creating the article is working fine, but I am having some trouble with creating the menu item.

I have the following code:

                //add the article to a menu item
                $menuTable = JTable::getInstance('Menu', 'JTable', array());

                    $menuData = array(
                    'menutype' => 'client-pages',
                    'title' => $data[name],
                    'type' => 'component',
                    'component_id' => 22,                  
                    'link' => 'index.php?option=com_content&view=article&id='.$resultID,
                    'language' => '*',
                    'published' => 1,
                    'parent_id' => '1',
                    'level' => 1,
                );

                // Bind data
                if (!$menuTable->bind($menuData))
                {
                    $this->setError($menuTable->getError());
                    return false;
                }

                // Check the data.
                if (!$menuTable->check())
                {
                    $this->setError($menuTable->getError());
                    return false;
                }

                // Store the data.
                if (!$menuTable->store())
                {
                    $this->setError($menuTable->getError());
                    return false;
                }

The error seems to be with setting the parent_id and level. On debugging libraries/joomla/database/tablenested.php sets the parent_id and level to 0. This caused the following error on my administrator page:

Warning: str_repeat() [function.str-repeat]: Second argument has to be greater than or equal to 0 in /Applications/MAMP/htdocs/joomla_2_5/administrator/components/com_menus/views/items/tmpl/default.php on line 129

4
It looks like that the error message is pretty specific what you did wrong. What's the problem to change that?hakre
The error message is pointing to a joomla core file so I don't want to hack around in there. I think I need to solve the problem of why joomla core keeps resetting my parent_id and level to 0Gaz_Edge

4 Answers

4
votes

Try using JTableNested::setLocation($referenceId, $position = 'after'):

$table->setLocation($parent_id, 'last-child');

I also think that you need to rebuild the path:

// Rebuild the tree path.
if (!$table->rebuildPath($table->id)) {
    $this->setError($table->getError());
    return false;
}

If it still doesn't work, try to find out what MenusModelItem::save does that you don't.

2
votes
$table->setLocation($parent_id, 'last-child');

is all that is needed to ensure that left/right values are created correctly for the new menu item. There is no need to rebuild the path as this is now handled by JTableMenu's store method.

Additionally, the convenience method "save" can be used to bind, check and store the menu item:

$menuItem = array(
            'menutype' => 'client-pages',
            'title' => $data[name],
            'type' => 'component',
            'component_id' => 22,                  
            'link' => 'index.php?option=com_content&view=article&id='.$resultID,
            'language' => '*',
            'published' => 1,
            'parent_id' => $parent_id,
            'level' => 1,
        );

$menuTable = JTable::getInstance('Menu', 'JTable', array());

$menuTable->setLocation($parent_id, 'last-child');

if (!$menuTable->save($menuItem)) {
    throw new Exception($menuTable->getError());
    return false;
}
1
votes

Somehow $menutable does not update parent_id and level in database table so you have to manually update those two fields by joomla query.

$menuTable = JTable::getInstance('Menu', 'JTable', array());

        $menuData = array(
            'menutype' => 'client-pages',
            'title' => $data[name],
            'type' => 'component',
            'component_id' => 22,                  
            'link' => 'index.php?option=com_content&view=article&id='.$resultID,
            'language' => '*',
            'published' => 1,
            'parent_id' => '1',
            'level' => 1,
        );

        // Bind data
        if (!$menuTable->bind($menuData))
        {
            $this->setError($menuTable->getError());
            return false;
        }

        // Check the data.
        if (!$menuTable->check())
        {
            $this->setError($menuTable->getError());
            return false;
        }

        // Store the data.
        if (!$menuTable->store())
        {
            $this->setError($menuTable->getError());
            return false;
        }

        $db   = $this->getDbo();
        $qry = "UPDATE `#__menu` SET `parent_id` = 1 , `level` = 1 WHERE `id` = ".$menuTable->id;
        $db->setQuery($qry);
        $db->query();
0
votes

This code worked for me

 JTable::addIncludePath(JPATH_ADMINISTRATOR.'/components/com_menus/tables/');

                $menuTable =& JTable::getInstance('menu', 'menusTable');

                $menuData = array(
                        'menutype' => 'client-pages',
                        'title' => 'mytrialmenu',
                        'type' => 'component',
                        'component_id' => 22,
                        'link' => 'index.php?option=index.php?                    option='com_content&view=article&id='.$resultID,
                        'language' => '*',
                        'published' => 1,
                        'parent_id' => 'choose some parent',
                        'level' => 1,
                );
                // Bind data
                if (!$row->bind($menuData))
                {
                    $this->setError($menuTable->getError());
                    return false;
                }

                // Check the data.
                if (!$row->check())
                {
                    $this->setError($menuTable->getError());
                    return false;
                }

                // Store the data.
                if (!$row->store())
                {
                    $this->setError($menuTable->getError());
                    return false;
                }

I think the reason is menusTable extends JnestedTable which is required for manipulating lft and rgt fields in the menu table