diff --git a/Controller/Direct.php b/Controller/Direct.php new file mode 100644 index 00000000..7e6a7308 --- /dev/null +++ b/Controller/Direct.php @@ -0,0 +1,133 @@ +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); + } +} diff --git a/Data/Modules.php b/Data/Modules.php index 312b08bf..f6f84a00 100644 --- a/Data/Modules.php +++ b/Data/Modules.php @@ -29,6 +29,7 @@ public function __construct() $this->addController('Xfrocks:Category', 'categories', ':int/'); $this->addController('Xfrocks:Conversation', 'conversations', ':int/'); $this->addController('Xfrocks:ConversationMessage', 'conversation-messages', ':int/'); + $this->addController('Xfrocks:Direct', 'direct', ':any/'); $this->addController('Xfrocks:Index', 'index'); $this->addController('Xfrocks:Forum', 'forums', ':int/'); $this->addController('Xfrocks:LostPassword', 'lost-password'); diff --git a/Transform/AbstractHandler.php b/Transform/AbstractHandler.php index 0e0942e9..a6a5f382 100644 --- a/Transform/AbstractHandler.php +++ b/Transform/AbstractHandler.php @@ -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); } /** diff --git a/Transform/Generic.php b/Transform/Generic.php index 6d81e617..3374d3a5 100644 --- a/Transform/Generic.php +++ b/Transform/Generic.php @@ -23,7 +23,7 @@ public function calculateDynamicValue(TransformContext $context, $key) public function canView(TransformContext $context) { - return true; + return false; } public function getMappings(TransformContext $context) diff --git a/Transform/LazyTransformer.php b/Transform/LazyTransformer.php index c4725479..6dcb275e 100644 --- a/Transform/LazyTransformer.php +++ b/Transform/LazyTransformer.php @@ -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); diff --git a/Transformer.php b/Transformer.php index 3654acb7..9aabd413 100644 --- a/Transformer.php +++ b/Transformer.php @@ -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 = [];