creocoder / yii2-nested-sets

The nested sets behavior for the Yii framework.
Other
446 stars 129 forks source link

appendTo does not properly update lft/rgt #47

Closed ptheofan closed 9 years ago

ptheofan commented 9 years ago

I use the following code to generate a categories tree out of a nested array. The code is updated to work with the latest version of nesteset. However when it runs all the lft/rgt columns appear to be wrong. With the prev. version (before the major update - renaming of classes, etc) this was not the case.

Is this a known bug?

(example code)

    /**
     * @param $tree
     * @param null $parentNode
     * @throws Exception
     * @throws \yii\base\ErrorException
     */
    protected function createTree($tree, $parentNode = null)
    {
        foreach($tree as $node) {
            $c = new Category();
            $c->name = $node['name'];

            if ($parentNode)
                $success = $c->appendTo($parentNode);
            else
                $success = $c->makeRoot();

            if (!$success)
                throw new Exception("Could not save node!\n".VarDumper::dumpAsString($c->errors));

            if (isset($node['items'])) {
                $this->createTree($node['items'], $c);
            }
        }
    }

    /**
     * This is a console action used to initialise the menu for the first time.
     * @throws Exception
     */
    public function actionReset()
    {
        $categoriesTree = [
            [
                'name' => 'Categories Demo',
                'url_key' => null,
                'items' => [
                    [
                        'name' => 'Eat and Drink',
                        'items' => [
                            [
                                'name' => 'Cafe',
                            ],
                            [
                                'name' => 'Bar',
                            ],
                            [
                                'name' => 'Restaurant',
                            ],
                            [
                                'name' => 'Fast Food',
                            ],
                        ],
                    ],
                    [
                        'name' => 'Sport',
                        'items' => [
                            [
                                'name' => 'Sportbar',
                            ],
                            [
                                'name' => 'Fitness',
                            ],
                            [
                                'name' => 'Bowling',
                            ],
                        ],
                    ],
                    [
                        'name' => 'Games',
                        'items' => [
                            [
                                'name' => 'Internet Cafe',
                            ],
                            [
                                'name' => 'Video Game Centre',
                            ],
                        ],
                    ],
                ],
            ],
        ];

        Category::deleteAll();
        $this->createTree($categoriesTree);
    }
Mihai-P commented 9 years ago

@ptheofan, with your code I got to this structure in the database Field Name root lft rgt depth Categories Demo 1 1 26 0 Eat and Drink 1 2 11 1 Cafe 1 3 4 2 Bar 1 5 6 2 Restaurant 1 7 8 2 Fast Food 1 9 10 2 Sport 1 12 19 1 Sportbar 1 13 14 2 Fitness 1 15 16 2 Bowling 1 17 18 2 Games 1 20 25 1 Internet Cafe 1 21 22 2 Video Game Centre 1 23 24 2

This is exactly what I would expect it to see regarding the tree. What were you expecting?

creocoder commented 9 years ago

@ptheofan Can't reproduce, can you provide your Category model dump?

ptheofan commented 9 years ago

I'm using multiroot version. The configuration of the behavior is the following

    /**
     * @return array
     */
    public function behaviors() {
        return [
            [
                'class' => NestedSetsBehavior::className(),
                'treeAttribute' => 'root',
                'depthAttribute' => 'level',
            ],
        ];
    }

Here's a table overview

id  root    lft rgt level   name    url_key icon    status  ts
139 139 1   2   0   Landmark Categories NULL    NULL    active  2015-01-10 12:45:55
140 139 2   3   1   Eat and Drink   eat-and-drink   NULL    active  2015-01-10 12:45:55
141 139 3   4   2   Cafe    cafe    NULL    active  2015-01-10 12:45:55
142 139 3   4   2   Bar bar NULL    active  2015-01-10 12:45:55
143 139 3   4   2   Restaurant  restaurant  NULL    active  2015-01-10 12:45:55
144 139 3   4   2   Fast Food   fast-food   NULL    active  2015-01-10 12:45:55
145 139 2   3   1   Sport   sport   NULL    active  2015-01-10 12:45:55
146 139 3   4   2   Sportbar    sportbar    NULL    active  2015-01-10 12:45:55
147 139 3   4   2   Fitness fitness NULL    active  2015-01-10 12:45:55
148 139 3   4   2   Bowling bowling NULL    active  2015-01-10 12:45:55
149 139 2   3   1   Games   games   NULL    active  2015-01-10 12:45:55
150 139 3   4   2   Internet Cafe   internet-cafe   NULL    active  2015-01-10 12:45:55
151 139 3   4   2   Video Game Centre   video-game-centre   NULL    active  2015-01-10 12:45:55
creocoder commented 9 years ago

@ptheofan Thanks for providing dump, will investigate situation and add new unit test cases if needed.

creocoder commented 9 years ago

@ptheofan Result of your example code is:

    id    tree     lft     rgt   depth  name               
------  ------  ------  ------  ------  -------------------
     1       1       1      26       0  Categories Demo    
     2       1       2      11       1  Eat and Drink      
     3       1       3       4       2  Cafe               
     4       1       5       6       2  Bar                
     5       1       7       8       2  Restaurant         
     6       1       9      10       2  Fast Food          
     7       1      12      19       1  Sport              
     8       1      13      14       2  Sportbar           
     9       1      15      16       2  Fitness            
    10       1      17      18       2  Bowling            
    11       1      20      25       1  Games              
    12       1      21      22       2  Internet Cafe      
    13       1      23      24       2  Video Game Centre  

So all fine. Also note that current code coverage is 98%, so all cases covered by tests. Please check again you use latest yii2-nested-sets version. Make sure you have:

"creocoder/yii2-nested-sets": "dev-master"

inside require section of composer.json.

Make composer update too. If you still have this bug provide full model dump please.

ptheofan commented 9 years ago

Hey man, found the issue. Packagist is not up to date. Maybe something you changed and forgot to update? So, according to packagist dev-master reference: 0fb841a

which of course is pretty old! I updated the code by hand and everything works fine.

Please remember to config packagist to automatically sync with master ;)

Cheers, P.

creocoder commented 9 years ago

@ptheofan Packagist version is automatically updated, this was done right after registering package on packagist. Make ensure you use creocoder\yii2-nested-sets instead of creocoder\yii2-nested-set-behavior since last package is replaced by first.

ptheofan commented 9 years ago

aha! That explains it all!!! Maybe it would be a good idea to put in the readme file a note for people that upgraded?

Thanks a lot man! Have a nice evening!

creocoder commented 9 years ago

@ptheofan Its already marked as abandoned on packagist. I assume composer should warn user if there is abandoned package and suggest switch to another package.