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

Optimizations for longrunning applications #569

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/.idea
composer.lock
build
vendor
.phpunit.result.cache
.phpunit.result.cache
9 changes: 5 additions & 4 deletions src/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* with the most. The manager has various configurable options, and allows users
* to create the "root scope" easily.
*/
class Manager
class Manager implements ManagerInterface
{
/**
* Array of scope identifiers for resources to include.
Expand Down Expand Up @@ -71,9 +71,9 @@ public function __construct(ScopeFactoryInterface $scopeFactory = null)
*/
public function createData(
ResourceInterface $resource,
?string $scopeIdentifier = null,
Scope $parentScopeInstance = null
): Scope {
?string $scopeIdentifier = null,
ScopeInterface $parentScopeInstance = null
): ScopeInterface {
if ($parentScopeInstance !== null) {
return $this->scopeFactory->createChildScopeFor($this, $parentScopeInstance, $resource, $scopeIdentifier);
}
Expand Down Expand Up @@ -197,6 +197,7 @@ public function parseFieldsets(array $fieldsets): self
}
return $this;
}

public function getRequestedFieldsets(): array
{
return $this->requestedFieldsets;
Expand Down
27 changes: 27 additions & 0 deletions src/ManagerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace League\Fractal;

use League\Fractal\Resource\ResourceInterface;
use League\Fractal\Serializer\Serializer;

interface ManagerInterface
{
public function getSerializer(): Serializer;

public function getIncludeParams(string $include): ParamBag;

public function getFieldset(string $type): ?ParamBag;

public function getRequestedFieldsets(): array;

public function getRequestedIncludes(): array;

public function getRequestedExcludes(): array;

public function createData(
ResourceInterface $resource,
?string $scopeIdentifier = null,
ScopeInterface $parentScopeInstance = null
): ScopeInterface;
}
1 change: 1 addition & 0 deletions src/Pagination/DoctrinePaginatorAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public function getTotal(): int
*/
public function getCount(): int
{
\assert($this->paginator->getIterator() instanceof Paginator);
return $this->paginator->getIterator()->count();
}

Expand Down
43 changes: 25 additions & 18 deletions src/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
use League\Fractal\Resource\NullResource;
use League\Fractal\Resource\ResourceInterface;
use League\Fractal\Serializer\Serializer;
use League\Fractal\Transformer\HasIncludesInterface;
use League\Fractal\Transformer\ScopeAwareInterface;

/**
* Scope
Expand All @@ -26,19 +28,19 @@
* context. For example, the same resource could be attached to multiple scopes.
* There are root scopes, parent scopes and child scopes.
*/
class Scope implements \JsonSerializable
class Scope implements \JsonSerializable, ScopeInterface
{
protected array $availableIncludes = [];

protected ?string $scopeIdentifier;

protected Manager $manager;
protected ManagerInterface $manager;

protected ResourceInterface $resource;

protected array $parentScopes = [];

public function __construct(Manager $manager, ResourceInterface $resource, ?string $scopeIdentifier = null)
public function __construct(ManagerInterface $manager, ResourceInterface $resource, ?string $scopeIdentifier = null)
{
$this->manager = $manager;
$this->resource = $resource;
Expand All @@ -50,7 +52,7 @@ public function __construct(Manager $manager, ResourceInterface $resource, ?stri
*
* @internal
*/
public function embedChildScope(string $scopeIdentifier, ResourceInterface $resource): Scope
public function embedChildScope(string $scopeIdentifier, ResourceInterface $resource): ScopeInterface
{
return $this->manager->createData($resource, $scopeIdentifier, $this);
}
Expand Down Expand Up @@ -87,7 +89,7 @@ public function getResource(): ResourceInterface
return $this->resource;
}

public function getManager(): Manager
public function getManager(): ManagerInterface
{
return $this->manager;
}
Expand Down Expand Up @@ -156,7 +158,7 @@ public function pushParentScope(string $identifierSegment): int
*
* @internal
*
* @param string[] $parentScopes Value to set.
* @param list<string> $parentScopes Value to set.
*/
public function setParentScopes(array $parentScopes): self
{
Expand All @@ -170,7 +172,7 @@ public function setParentScopes(array $parentScopes): self
*/
public function toArray(): ?array
{
list($rawData, $rawIncludedData) = $this->executeResourceTransformers();
[$rawData, $rawIncludedData] = $this->executeResourceTransformers();

$serializer = $this->manager->getSerializer();

Expand Down Expand Up @@ -269,8 +271,11 @@ public function transformPrimitiveResource()
} elseif (is_callable($transformer)) {
$transformedData = call_user_func($transformer, $data);
} else {
$transformer->setCurrentScope($this);
$transformedData = $transformer->transform($data);
if ($transformer instanceof ScopeAwareInterface) {
$transformer->setCurrentScope($this);
}
\assert(\method_exists($transformer, 'transform'));
$transformedData = $transformer->transform($data, $this);
}

return $transformedData;
Expand All @@ -289,10 +294,10 @@ protected function executeResourceTransformers(): array
$transformedData = $includedData = [];

if ($this->resource instanceof Item) {
list($transformedData, $includedData[]) = $this->fireTransformer($transformer, $data);
[$transformedData, $includedData[]] = $this->fireTransformer($transformer, $data);
} elseif ($this->resource instanceof Collection) {
foreach ($data as $value) {
list($transformedData[], $includedData[]) = $this->fireTransformer($transformer, $value);
[$transformedData[], $includedData[]] = $this->fireTransformer($transformer, $value);
}
} elseif ($this->resource instanceof NullResource) {
$transformedData = null;
Expand Down Expand Up @@ -343,7 +348,7 @@ protected function serializeResource(Serializer $serializer, $data): ?array
*
* @internal
*
* @param TransformerAbstract|callable $transformer
* @param object|callable $transformer
* @param mixed $data
*/
protected function fireTransformer($transformer, $data): array
Expand All @@ -353,8 +358,11 @@ protected function fireTransformer($transformer, $data): array
if (is_callable($transformer)) {
$transformedData = call_user_func($transformer, $data);
} else {
$transformer->setCurrentScope($this);
$transformedData = $transformer->transform($data);
if ($transformer instanceof ScopeAwareInterface) {
$transformer->setCurrentScope($this);
}
\assert(\method_exists($transformer, 'transform'));
$transformedData = $transformer->transform($data, $this);
}

if ($this->transformerHasIncludes($transformer)) {
Expand All @@ -373,10 +381,9 @@ protected function fireTransformer($transformer, $data): array
*
* @internal
*
* @param \League\Fractal\TransformerAbstract $transformer
* @param mixed $data
*/
protected function fireIncludedTransformers($transformer, $data): array
protected function fireIncludedTransformers(HasIncludesInterface $transformer, $data): array
{
$this->availableIncludes = $transformer->getAvailableIncludes();

Expand All @@ -388,11 +395,11 @@ protected function fireIncludedTransformers($transformer, $data): array
*
* @internal
*
* @param TransformerAbstract|callable $transformer
* @param object|HasIncludesInterface|callable $transformer
*/
protected function transformerHasIncludes($transformer): bool
{
if (! $transformer instanceof TransformerAbstract) {
if (! $transformer instanceof HasIncludesInterface) {
return false;
}

Expand Down
16 changes: 9 additions & 7 deletions src/ScopeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,21 @@
class ScopeFactory implements ScopeFactoryInterface
{
public function createScopeFor(
Manager $manager,
ManagerInterface $manager,
ResourceInterface $resource,
?string $scopeIdentifier = null
): Scope {
?string $scopeIdentifier = null
): ScopeInterface
{
return new Scope($manager, $resource, $scopeIdentifier);
}

public function createChildScopeFor(
Manager $manager,
Scope $parentScope,
ManagerInterface $manager,
ScopeInterface $parentScope,
ResourceInterface $resource,
?string $scopeIdentifier = null
): Scope {
?string $scopeIdentifier = null
): ScopeInterface
{
$scopeInstance = $this->createScopeFor($manager, $resource, $scopeIdentifier);

// This will be the new children list of parents (parents parents, plus the parent)
Expand Down
14 changes: 7 additions & 7 deletions src/ScopeFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@
interface ScopeFactoryInterface
{
public function createScopeFor(
Manager $manager,
ManagerInterface $manager,
ResourceInterface $resource,
?string $scopeIdentifier = null
): Scope;
?string $scopeIdentifier = null
): ScopeInterface;

public function createChildScopeFor(
Manager $manager,
Scope $parentScope,
ManagerInterface $manager,
ScopeInterface $parentScope,
ResourceInterface $resource,
?string $scopeIdentifier = null
): Scope;
?string $scopeIdentifier = null
): ScopeInterface;
}
35 changes: 35 additions & 0 deletions src/ScopeInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace League\Fractal;

use League\Fractal\Resource\ResourceInterface;

interface ScopeInterface
{
public function getManager(): ManagerInterface;

public function getResource(): ResourceInterface;

public function toArray(): ?array;

public function getScopeIdentifier(): ?string;

public function getIdentifier(?string $appendIdentifier = null): string;

public function embedChildScope(string $scopeIdentifier, ResourceInterface $resource): ScopeInterface;

public function pushParentScope(string $identifierSegment): int;

public function getParentScopes();

public function isExcluded(string $checkScopeSegment): bool;

public function isRequested(string $checkScopeSegment): bool;

public function transformPrimitiveResource();

/**
* @param list<string> $parentScopes
*/
public function setParentScopes(array $parentScopes): self;
}
24 changes: 24 additions & 0 deletions src/Transformer/HasIncludesInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace League\Fractal\Transformer;

use League\Fractal\ScopeInterface;

interface HasIncludesInterface
{
/**
* @return list<non-empty-string>
*/
public function getAvailableIncludes(): array;

/**
* @return list<non-empty-string>
*/
public function getDefaultIncludes(): array;

/**
* @param mixed $data
* @return mixed
*/
public function processIncludedResources(ScopeInterface $scope, $data);
}
Loading