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

Implement support for GET /direct #123

Open
wants to merge 1 commit into
base: xenforo2
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
133 changes: 133 additions & 0 deletions Controller/Direct.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

namespace Xfrocks\Api\Controller;

use XF\Mvc\ParameterBag;
use Xfrocks\Api\Transform\TransformContext;
use Xfrocks\Api\Transformer;

class Direct extends AbstractController
{
public function actionGetIndex(ParameterBag $params)
{
$paramType = $params->type;
$params = $this->params()
->define('where', 'array');

$types = explode('/', $paramType);
$type0 = array_shift($types);
$subTypes = $types;
unset($types);

$rootFinder = $this->finder($type0);

$where = $params['where'];
$input = $this->request->getInput();
foreach ($input as $inputKey => $inputValue) {
if (empty($inputValue)) {
continue;
}
if (isset($params[$inputKey])) {
continue;
}
$where[] = [$inputKey, '=', $inputValue];
}
foreach ($where as $whereOne) {
if (!is_array($whereOne)) {
continue;
}
try {
call_user_func_array([$rootFinder, 'where'], array_values($whereOne));
} catch (\InvalidArgumentException $e) {
// bad condition, ignore
}
}

$transformer = $this->transformFinderLazily($rootFinder);
$rootContext = $params->getTransformContext();

if (count($subTypes) > 0) {
$rootContext->onTransformFinderCallbacks[] = function ($context, $finder) use (
$rootContext,
$rootFinder,
$subTypes
) {
if ($context !== $rootContext || $finder !== $rootFinder) {
return;
}

/** @var TransformContext $context */
/** @var \XF\Mvc\Entity\Finder $finder */
/** @var Transformer $transformer */
$transformer = $this->app->container('api.transformer');
$subContext = $context;
$subFinder = $finder;
foreach ($subTypes as $subType) {
try {
$subFinder->with($subType);
} catch (\LogicException $e) {
// bad relation key, return asap
return;
}

$entityStructure = $subFinder->getStructure();
$relationConfig = $entityStructure->relations[$subType];
$subHandler = $transformer->handler($relationConfig['entity']);

$em = $this->app->em();
$parentFinder = $subFinder;
$subFinder = $em->getFinder($relationConfig['entity'], false);
$subFinder->setParentFinder($parentFinder, $subType);

$subContext = $subContext->getSubContext(null, $subHandler);
$subHandler->onTransformFinder($subContext, $subFinder);
}
};

$transformer->addCallbackFinderPostFetch(function ($entities) use ($subTypes) {
$subEntities = [];

/** @var \XF\Mvc\Entity\Entity $entity */
foreach ($entities as $entity) {
if (!$this->canView($entity)) {
continue;
}

foreach ($subTypes as $subType) {
try {
$entity = $entity->getRelation($subType);
} catch (\InvalidArgumentException $e) {
// bad relation key, return asap
return $subEntities;
}
if (!$this->canView($entity)) {
continue;
}
}

$subEntities[] = $entity;
}

return $subEntities;
});
}

$data = [$paramType => $transformer];

return $this->api($data);
}

/**
* @param \XF\Mvc\Entity\Entity $entity
* @return bool|mixed
*/
protected function canView(\XF\Mvc\Entity\Entity $entity)
{
$callable = [$entity, 'canView'];
if (!is_callable($callable)) {
return false;
}

return call_user_func($callable);
}
}
1 change: 1 addition & 0 deletions Data/Modules.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function __construct()
$this->addController('Xfrocks:Category', 'categories', ':int<node_id>/');
$this->addController('Xfrocks:Conversation', 'conversations', ':int<conversation_id>/');
$this->addController('Xfrocks:ConversationMessage', 'conversation-messages', ':int<message_id>/');
$this->addController('Xfrocks:Direct', 'direct', ':any<type>/');
$this->addController('Xfrocks:Index', 'index');
$this->addController('Xfrocks:Forum', 'forums', ':int<node_id>/');
$this->addController('Xfrocks:LostPassword', 'lost-password');
Expand Down
39 changes: 7 additions & 32 deletions Transform/AbstractHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -275,51 +275,26 @@ protected function callOnTransformEntitiesForRelation(
* @param Finder $finder
* @param string|null $contextKey
* @param string $relationKey
* @param string|null $shortName
* @return void
*/
protected function callOnTransformFinderForRelation(
TransformContext $context,
Finder $finder,
$contextKey,
$relationKey,
$shortName = null
$relationKey
) {
$finder->with($relationKey);

if ($shortName === null) {
$shortName = $this->type;
}

$em = $this->app->em();
$entityStructure = $em->getEntityStructure($shortName);
if (!isset($entityStructure->relations[$relationKey])) {
return;
}

$entityStructure = $finder->getStructure();
$relationConfig = $entityStructure->relations[$relationKey];
if (!is_array($relationConfig) || !isset($relationConfig['entity'])) {
return;
}

$subHandler = $this->transformer->handler($relationConfig['entity']);
$subContext = $context->getSubContext($contextKey, $subHandler);

$relationStructure = $em->getEntityStructure($relationConfig['entity']);
$finderClass = \XF::stringToClass($shortName, '%s\Finder\%s');
try {
$finderClass = $this->app->extendClass($finderClass, '\XF\Mvc\Entity\Finder');
} catch (\Exception $e) {
// ignore
}
if (!$finderClass || !class_exists($finderClass)) {
$finderClass = '\XF\Mvc\Entity\Finder';
}
/** @var Finder $relationFinder */
$relationFinder = new $finderClass($em, $relationStructure);
$relationFinder->setParentFinder($finder, $relationKey);
$em = $this->app->em();
$subFinder = $em->getFinder($relationConfig['entity'], false);
$subFinder->setParentFinder($finder, $relationKey);

$subHandler->onTransformFinder($subContext, $relationFinder);
$subContext = $context->getSubContext($contextKey, $subHandler);
$subHandler->onTransformFinder($subContext, $subFinder);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion Transform/Generic.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public function calculateDynamicValue(TransformContext $context, $key)

public function canView(TransformContext $context)
{
return true;
return false;
}

public function getMappings(TransformContext $context)
Expand Down
18 changes: 12 additions & 6 deletions Transform/LazyTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,19 @@ public function transform()
case self::SOURCE_TYPE_FINDER:
/** @var Finder $finder */
$finder = $this->source;
$data = $transformer->transformFinder($context, null, $finder, function ($entities) {
foreach (array_reverse($this->callbacksFinderPostFetch) as $f) {
$entities = call_user_func($f, $entities);
}

return $entities;
});
$postFetchCallback = null;
if (count($this->callbacksFinderPostFetch) > 0) {
$postFetchCallback = function ($entities) {
foreach (array_reverse($this->callbacksFinderPostFetch) as $f) {
$entities = call_user_func($f, $entities);
}

return $entities;
};
}

$data = $transformer->transformFinder($context, null, $finder, $postFetchCallback);
break;
default:
throw new \LogicException('Unrecognized source type ' . $this->sourceType);
Expand Down
4 changes: 4 additions & 0 deletions Transformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ public function transformFinder($context, $key, $finder, $postFetchCallback = nu
if ($entities instanceof \XF\Mvc\Entity\ArrayCollection) {
$entities = $entities->toArray();
}
if ($postFetchCallback && count($entities) > 0) {
// postFetchCallback might have returned a different type of entity
$handler = $this->handler($entities[0]->structure()->shortName);
}
$entities = $handler->onTransformEntities($context, $entities);

$data = [];
Expand Down