Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document stdClass structures used by CommitOrderCalculator #10315

Merged
merged 1 commit into from
Dec 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Upgrade to 2.14

## Deprecated constants of `Doctrine\ORM\Internal\CommitOrderCalculator`

The following public constants have been deprecated:

* `CommitOrderCalculator::NOT_VISITED`
* `CommitOrderCalculator::IN_PROGRESS`
* `CommitOrderCalculator::VISITED`

These constants were used for internal purposes. Relying on them is discouraged.

## Deprecated `Doctrine\ORM\Query\AST\InExpression`

The AST parser will create a `InListExpression` or a `InSubselectExpression` when
Expand Down
34 changes: 34 additions & 0 deletions lib/Doctrine/ORM/Internal/CommitOrder/Edge.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Doctrine\ORM\Internal\CommitOrder;

/** @internal */
final class Edge
{
/**
* @var string
* @readonly
*/
public $from;

/**
* @var string
* @readonly
*/
public $to;

/**
* @var int
* @readonly
*/
public $weight;

public function __construct(string $from, string $to, int $weight)
{
$this->from = $from;
$this->to = $to;
$this->weight = $weight;
}
}
38 changes: 38 additions & 0 deletions lib/Doctrine/ORM/Internal/CommitOrder/Vertex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Doctrine\ORM\Internal\CommitOrder;

use Doctrine\ORM\Mapping\ClassMetadata;

/** @internal */
final class Vertex
{
/**
* @var string
* @readonly
*/
public $hash;

/**
* @var int
* @psalm-var VertexState::*
*/
public $state = VertexState::NOT_VISITED;

/**
* @var ClassMetadata
* @readonly
*/
public $value;

/** @var array<string, Edge> */
public $dependencyList = [];

public function __construct(string $hash, ClassMetadata $value)
{
$this->hash = $hash;
$this->value = $value;
}
}
17 changes: 17 additions & 0 deletions lib/Doctrine/ORM/Internal/CommitOrder/VertexState.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Doctrine\ORM\Internal\CommitOrder;

/** @internal */
final class VertexState
{
public const NOT_VISITED = 0;
public const IN_PROGRESS = 1;
public const VISITED = 2;

private function __construct()
{
}
}
77 changes: 31 additions & 46 deletions lib/Doctrine/ORM/Internal/CommitOrderCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

namespace Doctrine\ORM\Internal;

use stdClass;
use Doctrine\ORM\Internal\CommitOrder\Edge;
use Doctrine\ORM\Internal\CommitOrder\Vertex;
use Doctrine\ORM\Internal\CommitOrder\VertexState;
use Doctrine\ORM\Mapping\ClassMetadata;

use function array_reverse;

Expand All @@ -17,33 +20,28 @@
*/
class CommitOrderCalculator
{
public const NOT_VISITED = 0;
public const IN_PROGRESS = 1;
public const VISITED = 2;
/** @deprecated */
public const NOT_VISITED = VertexState::NOT_VISITED;

/** @deprecated */
public const IN_PROGRESS = VertexState::IN_PROGRESS;

/** @deprecated */
public const VISITED = VertexState::VISITED;
derrabus marked this conversation as resolved.
Show resolved Hide resolved

/**
* Matrix of nodes (aka. vertex).
* Keys are provided hashes and values are the node definition objects.
*
* The node state definition contains the following properties:
*
* - <b>state</b> (integer)
* Whether the node is NOT_VISITED or IN_PROGRESS
*
* - <b>value</b> (object)
* Actual node value
*
* - <b>dependencyList</b> (array<string>)
* Map of node dependencies defined as hashes.
* Keys are provided hashes and values are the node definition objects.
*
* @var array<stdClass>
* @var array<string, Vertex>
*/
private $nodeList = [];

/**
* Volatile variable holding calculated nodes during sorting process.
*
* @psalm-var list<object>
* @psalm-var list<ClassMetadata>
*/
private $sortedNodeList = [];

Expand All @@ -62,21 +60,14 @@ public function hasNode($hash)
/**
* Adds a new node (vertex) to the graph, assigning its hash and value.
*
* @param string $hash
* @param object $node
* @param string $hash
* @param ClassMetadata $node
*
* @return void
*/
public function addNode($hash, $node)
{
$vertex = new stdClass();

$vertex->hash = $hash;
$vertex->state = self::NOT_VISITED;
$vertex->value = $node;
$vertex->dependencyList = [];

$this->nodeList[$hash] = $vertex;
$this->nodeList[$hash] = new Vertex($hash, $node);
}

/**
Expand All @@ -90,14 +81,8 @@ public function addNode($hash, $node)
*/
public function addDependency($fromHash, $toHash, $weight)
{
$vertex = $this->nodeList[$fromHash];
$edge = new stdClass();

$edge->from = $fromHash;
$edge->to = $toHash;
$edge->weight = $weight;

$vertex->dependencyList[$toHash] = $edge;
$this->nodeList[$fromHash]->dependencyList[$toHash]
= new Edge($fromHash, $toHash, $weight);
}

/**
Expand All @@ -106,12 +91,12 @@ public function addDependency($fromHash, $toHash, $weight)
*
* {@internal Highly performance-sensitive method.}
*
* @psalm-return list<object>
* @psalm-return list<ClassMetadata>
*/
public function sort()
{
foreach ($this->nodeList as $vertex) {
if ($vertex->state !== self::NOT_VISITED) {
if ($vertex->state !== VertexState::NOT_VISITED) {
continue;
}

Expand All @@ -131,19 +116,19 @@ public function sort()
*
* {@internal Highly performance-sensitive method.}
*/
private function visit(stdClass $vertex): void
private function visit(Vertex $vertex): void
{
$vertex->state = self::IN_PROGRESS;
$vertex->state = VertexState::IN_PROGRESS;

foreach ($vertex->dependencyList as $edge) {
$adjacentVertex = $this->nodeList[$edge->to];

switch ($adjacentVertex->state) {
case self::VISITED:
case VertexState::VISITED:
// Do nothing, since node was already visited
break;

case self::IN_PROGRESS:
case VertexState::IN_PROGRESS:
if (
isset($adjacentVertex->dependencyList[$vertex->hash]) &&
$adjacentVertex->dependencyList[$vertex->hash]->weight < $edge->weight
Expand All @@ -153,25 +138,25 @@ private function visit(stdClass $vertex): void
foreach ($adjacentVertex->dependencyList as $adjacentEdge) {
$adjacentEdgeVertex = $this->nodeList[$adjacentEdge->to];

if ($adjacentEdgeVertex->state === self::NOT_VISITED) {
if ($adjacentEdgeVertex->state === VertexState::NOT_VISITED) {
$this->visit($adjacentEdgeVertex);
}
}

$adjacentVertex->state = self::VISITED;
$adjacentVertex->state = VertexState::VISITED;

$this->sortedNodeList[] = $adjacentVertex->value;
}

break;

case self::NOT_VISITED:
case VertexState::NOT_VISITED:
$this->visit($adjacentVertex);
}
}

if ($vertex->state !== self::VISITED) {
$vertex->state = self::VISITED;
if ($vertex->state !== VertexState::VISITED) {
$vertex->state = VertexState::VISITED;

$this->sortedNodeList[] = $vertex->value;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Doctrine/ORM/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -1281,7 +1281,7 @@ private function executeDeletions(ClassMetadata $class): void
/**
* Gets the commit order.
*
* @return list<object>
* @return list<ClassMetadata>
*/
private function getCommitOrder(): array
{
Expand Down
12 changes: 2 additions & 10 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -410,13 +410,9 @@
</UndefinedMethod>
</file>
<file src="lib/Doctrine/ORM/Internal/CommitOrderCalculator.php">
<InvalidPropertyAssignmentValue occurrences="2">
<code>$this-&gt;sortedNodeList</code>
<code>$this-&gt;sortedNodeList</code>
</InvalidPropertyAssignmentValue>
<RedundantCondition occurrences="2">
<code>$vertex-&gt;state !== self::VISITED</code>
<code>$vertex-&gt;state !== self::VISITED</code>
<code>$vertex-&gt;state !== VertexState::VISITED</code>
<code>$vertex-&gt;state !== VertexState::VISITED</code>
</RedundantCondition>
</file>
<file src="lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php">
Expand Down Expand Up @@ -2895,10 +2891,6 @@
</UnresolvableInclude>
</file>
<file src="lib/Doctrine/ORM/UnitOfWork.php">
<ArgumentTypeCoercion occurrences="2">
<code>$class</code>
<code>$class</code>
</ArgumentTypeCoercion>
<DocblockTypeContradiction occurrences="2">
<code>! is_object($object)</code>
<code>is_object($object)</code>
Expand Down