Skip to content
Open
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: 5 additions & 5 deletions ProcessMaker/Nayra/Repositories/EntityRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

abstract class EntityRepository
{
private static $uid2id = ['requests' =>[], 'tokens' =>[]];
private $uid2id = ['requests' =>[], 'tokens' =>[]];

abstract public function create(array $transaction): ? Model;

Expand Down Expand Up @@ -41,16 +41,16 @@ public function resolveId(string $uid): int
}

// Get record if is not stored previously
if (!isset(self::$uid2id[$type][$uid])) {
if (!isset($this->uid2id[$type][$uid])) {
$record = $instance->select('id')->where('uuid', $uid)->first();
if ($record) {
self::$uid2id[$type][$uid] = $record->getKey();
$this->uid2id[$type][$uid] = $record->getKey();
} else {
throw new Exception("The uid {$uid} does not exist in the database");
}
}

return self::$uid2id[$type][$uid] ?? 0;
return $this->uid2id[$type][$uid] ?? 0;
}

/**
Expand All @@ -71,6 +71,6 @@ public function storeUid(string $uid, int $id): void
break;
}

self::$uid2id[$type][$uid] = $id;
$this->uid2id[$type][$uid] = $id;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace Tests\Unit\ProcessMaker\Nayra\Repositories;

use Illuminate\Database\Eloquent\Model;
use ProcessMaker\Nayra\Repositories\EntityRepository;
use ReflectionProperty;
use Tests\TestCase;

class EntityRepositoryTest extends TestCase
{
/**
* Create a concrete implementation of EntityRepository for testing.
*/
private function createRepository(): EntityRepository
{
return new class extends EntityRepository {
public function create(array $transaction): ?Model
{
return null;
}

public function update(array $transaction): ?Model
{
return null;
}

public function save(array $transaction): ?Model
{
return null;
}
};
}

/**
* Test that $uid2id is NOT a static property (fix for Octane data leak).
*
* In Octane, static properties persist across requests. The critical fix
* changes $uid2id from "private static" to "private" so that each instance
* has its own isolated cache, preventing data leaks between requests.
*/
public function test_uid2id_is_not_static(): void
{
$reflection = new ReflectionProperty(EntityRepository::class, 'uid2id');

$this->assertFalse(
$reflection->isStatic(),
'uid2id must NOT be static to prevent data leaks between requests in Octane'
);
}

/**
* Test that $uid2id is a private property.
*/
public function test_uid2id_is_private(): void
{
$reflection = new ReflectionProperty(EntityRepository::class, 'uid2id');

$this->assertTrue(
$reflection->isPrivate(),
'uid2id should be private'
);
}
}
Loading