Skip to content

Duplicate position after repositioning #2997

@alexsegura

Description

@alexsegura

Environment

Package

show

$ composer show --latest gedmo/doctrine-extensions
name     : gedmo/doctrine-extensions
descrip. : Doctrine behavioral extensions
keywords : Blameable, behaviors, doctrine, extensions, gedmo, loggable, nestedset, odm, orm, sluggable, sortable, timestampable, translatable, tree, uploadable
versions : * v3.21.0
latest   : v3.21.0
type     : library
license  : MIT License (MIT) (OSI approved) https://spdx.org/licenses/MIT.html#licenseText
homepage : http://gediminasm.org/
source   : [git] https://github.com/doctrine-extensions/DoctrineExtensions.git eb53dfcb2b592327b76ac5226fbb003d32aea37e
dist     : [zip] https://api.github.com/repos/doctrine-extensions/DoctrineExtensions/zipball/eb53dfcb2b592327b76ac5226fbb003d32aea37e eb53dfcb2b592327b76ac5226fbb003d32aea37e
path     : /Users/admin/Workspace/coopcycle-web/vendor/gedmo/doctrine-extensions
names    : gedmo/doctrine-extensions

Doctrine packages

show

$ composer show --latest 'doctrine/*'
Direct dependencies required in composer.json:
doctrine/annotations     2.0.2  2.0.2  Docblock Annotations Parser
Package doctrine/annotations is abandoned, you should avoid using it. No replacement was suggested.
doctrine/cache           2.2.0  2.2.0  PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.
Package doctrine/cache is abandoned, you should avoid using it. No replacement was suggested.
doctrine/collections     2.3.0  2.3.0  PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.
doctrine/common          3.5.0  3.5.0  PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and muc...
doctrine/dbal            4.3.4  4.3.4  Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.
doctrine/deprecations    1.1.5  1.1.5  A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.
doctrine/doctrine-bundle 2.17.1 2.17.1 Symfony DoctrineBundle
doctrine/event-manager   2.0.1  2.0.1  The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.
doctrine/mongodb-odm     2.12.2 1.0.8  PHP Doctrine MongoDB Object Document Mapper (ODM) provides transparent persistence for PHP objects to MongoDB.
doctrine/orm             3.5.2  3.5.2  Object-Relational-Mapper for PHP
doctrine/persistence     4.1.0  4.1.0  The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.

Transitive dependencies not required in composer.json:
doctrine/inflector       2.1.0  2.1.0  PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.
doctrine/instantiator    2.0.0  2.0.0  A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer           3.0.1  3.0.1  PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.
doctrine/sql-formatter   1.5.2  1.5.2  a PHP SQL highlighting library

PHP version

$ php -v
PHP 8.3.22 (cli) (built: Jun  3 2025 17:17:57) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.3.22, Copyright (c) Zend Technologies
    with Zend OPcache v8.3.22, Copyright (c), by Zend Technologies

Subject

When repositioning a node + adding a new node, positions are duplicated, resulting in a unpredictable order.

Minimal repository with the bug

I added a unit test in this repository, in the branch wrong-position, that confirms the problem

Steps to reproduce

$node1 = new Node();
$node1->setName('Node1');
$node1->setPath('/');
$node1->setPosition(0);
$this->em->persist($node1);

$node2 = new Node();
$node2->setName('Node2');
$node2->setPath('/');
$node2->setPosition(1);
$this->em->persist($node2);

$node3 = new Node();
$node3->setName('Node3');
$node3->setPath('/');
$node3->setPosition(2);
$this->em->persist($node3);

$this->em->flush();

// We change position of Node3 (it will be the last)
$node3->setPosition(3);

// We insert a node at position 2 (it will be before Node3)
$node4 = new Node();
$node4->setName('Node4');
$node4->setPath('/');
$node4->setPosition(2);

$this->em->persist($node3);
$this->em->persist($node4);
$this->em->flush();

Expected results

Elements shouldn't have the same position.

Actual results

Both Node3 & Node4 have the position 2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions