/** * Add the current node and all parent identifiers to be used for cache entry tagging * * @Flow\Before("method(Neos\Flow\Mvc\Routing\RouterCachingService->extractUuids())") * @param JoinPointInterface $joinPoint The current join point * @return void */ public function addCurrentNodeIdentifier(JoinPointInterface $joinPoint) { $values = $joinPoint->getMethodArgument('values'); if (!isset($values['node']) || strpos($values['node'], '@') === false) { return; } // Build context explicitly without authorization checks because the security context isn't available yet // anyway and any Entity Privilege targeted on Workspace would fail at this point: $this->securityContext->withoutAuthorizationChecks(function () use($joinPoint, $values) { $contextPathPieces = NodePaths::explodeContextPath($values['node']); $context = $this->contextFactory->create(['workspaceName' => $contextPathPieces['workspaceName'], 'dimensions' => $contextPathPieces['dimensions'], 'invisibleContentShown' => true]); $node = $context->getNode($contextPathPieces['nodePath']); if (!$node instanceof NodeInterface) { return; } $values['node-identifier'] = $node->getIdentifier(); $node = $node->getParent(); $values['node-parent-identifier'] = array(); while ($node !== null) { $values['node-parent-identifier'][] = $node->getIdentifier(); $node = $node->getParent(); } $joinPoint->setMethodArgument('values', $values); }); }
/** * Before advice, making sure we initialize before use. * * This expects $proxy->Flow_Persistence_LazyLoadingObject_thawProperties * to be a Closure that populates the object. That variable is unset after * initializing the object! * * @param JoinPointInterface $joinPoint The current join point * @return void * @Flow\Before("Neos\Flow\Persistence\Generic\Aspect\LazyLoadingObjectAspect->needsLazyLoadingObjectAspect && !method(.*->__construct())") */ public function initialize(JoinPointInterface $joinPoint) { $proxy = $joinPoint->getProxy(); if (property_exists($proxy, 'Flow_Persistence_LazyLoadingObject_thawProperties') && $proxy->Flow_Persistence_LazyLoadingObject_thawProperties instanceof \Closure) { $proxy->Flow_Persistence_LazyLoadingObject_thawProperties->__invoke($proxy); unset($proxy->Flow_Persistence_LazyLoadingObject_thawProperties); } }
/** * Convert the object to its context path, if we deal with ContentRepository nodes. * * @Flow\Around("method(Neos\Flow\Persistence\AbstractPersistenceManager->convertObjectToIdentityArray())") * @param JoinPointInterface $joinPoint the joinpoint * @return string|array the context path to be used for routing */ public function convertNodeToContextPathForRouting(JoinPointInterface $joinPoint) { $objectArgument = $joinPoint->getMethodArgument('object'); if ($objectArgument instanceof NodeInterface) { return $objectArgument->getContextPath(); } else { return $joinPoint->getAdviceChain()->proceed($joinPoint); } }
/** * Invokes a given join point * * @param \Neos\Flow\Aop\JoinPointInterface $joinPoint * @return mixed */ public function Flow_Aop_Proxy_invokeJoinPoint(\Neos\Flow\Aop\JoinPointInterface $joinPoint) { if (__CLASS__ !== $joinPoint->getClassName()) { return parent::Flow_Aop_Proxy_invokeJoinPoint($joinPoint); } if (isset($this->Flow_Aop_Proxy_methodIsInAdviceMode[$joinPoint->getMethodName()])) { return call_user_func_array(['self', $joinPoint->getMethodName()], $joinPoint->getMethodArguments()); } }
/** * @Flow\Around("method(Neos\ContentRepository\Domain\Model\NodeType->__construct())") * @return void */ public function enrichNodeTypeConfiguration(JoinPointInterface $joinPoint) { $configuration = $joinPoint->getMethodArgument('configuration'); $nodeTypeName = $joinPoint->getMethodArgument('name'); $this->addEditorDefaultsToNodeTypeConfiguration($nodeTypeName, $configuration); $this->addLabelsToNodeTypeConfiguration($nodeTypeName, $configuration); $joinPoint->setMethodArgument('configuration', $configuration); $joinPoint->getAdviceChain()->proceed($joinPoint); }
/** * @test * @return void */ public function generateUuidGeneratesUuidAndRegistersProxyAsNewObject() { $className = 'Class' . md5(uniqid(mt_rand(), true)); eval('class ' . $className . ' implements \\Neos\\Flow\\Persistence\\Aspect\\PersistenceMagicInterface { public $Persistence_Object_Identifier = NULL; }'); $object = new $className(); $this->mockJoinPoint->expects($this->atLeastOnce())->method('getProxy')->will($this->returnValue($object)); $this->mockPersistenceManager->expects($this->atLeastOnce())->method('registerNewObject')->with($object); $this->persistenceMagicAspect->generateUuid($this->mockJoinPoint); $this->assertEquals(36, strlen($object->Persistence_Object_Identifier)); }
/** * @Flow\Around("setting(Neos.Neos.typoScript.enableObjectTreeCache) && method(Neos\Neos\Domain\Service\TypoScriptService->getMergedTypoScriptObjectTree())") * @param JoinPointInterface $joinPoint The current join point * @return mixed */ public function cacheGetMergedTypoScriptObjectTree(JoinPointInterface $joinPoint) { $currentSiteNode = $joinPoint->getMethodArgument('startNode'); $cacheIdentifier = str_replace('.', '_', $currentSiteNode->getContext()->getCurrentSite()->getSiteResourcesPackageKey()); if ($this->typoScriptCache->has($cacheIdentifier)) { $typoScriptObjectTree = $this->typoScriptCache->get($cacheIdentifier); } else { $typoScriptObjectTree = $joinPoint->getAdviceChain()->proceed($joinPoint); $this->typoScriptCache->set($cacheIdentifier, $typoScriptObjectTree); } return $typoScriptObjectTree; }
/** * @test * @todo adjust when AfterInvocationInterceptor is used again */ public function enforcePolicyDoesNotInvokeInterceptorIfAuthorizationChecksAreDisabled() { $this->mockAdviceChain->expects($this->once())->method('proceed')->with($this->mockJoinPoint); $this->mockJoinPoint->expects($this->once())->method('getAdviceChain')->will($this->returnValue($this->mockAdviceChain)); $this->mockSecurityContext->expects($this->atLeastOnce())->method('areAuthorizationChecksDisabled')->will($this->returnValue(true)); $this->mockPolicyEnforcementInterceptor->expects($this->never())->method('invoke'); $this->policyEnforcementAspect->enforcePolicy($this->mockJoinPoint); }
/** * Returns a string message, giving insights what happened during privilege evaluation. * * @param string $privilegeReasonMessage * @return string */ protected function renderDecisionReasonMessage($privilegeReasonMessage) { if (count($this->securityContext->getRoles()) === 0) { $rolesMessage = 'No authenticated roles'; } else { $rolesMessage = 'Authenticated roles: ' . implode(', ', array_keys($this->securityContext->getRoles())); } return sprintf('Access denied for method' . chr(10) . 'Method: %s::%s()' . chr(10) . chr(10) . '%s' . chr(10) . chr(10) . '%s', $this->joinPoint->getClassName(), $this->joinPoint->getMethodName(), $privilegeReasonMessage, $rolesMessage); }
/** * @param JoinPointInterface $joinPoint * @param string $profilePath * @return ProfileInterface */ protected function profile(JoinPointInterface $joinPoint, $profilePath) { /** @var PaletteInterface $proxy */ $proxy = $joinPoint->getProxy(); try { $profile = ObjectAccess::getProperty($proxy, 'profile', TRUE); } catch (\Exception $exception) { // Getting the profile will fail on the CMYK palette as the profile property is private and as the class // has to be reflected this private property will be on the _Original class and not on the proxy class and // is as such not accessible for property_exists in ObjectAccess::getProperty // @see NEOS-423 return $this->createAndSetProfileOnProxy($proxy, $profilePath); } if (!$profile instanceof ProfileInterface) { $profile = $this->createAndSetProfileOnProxy($proxy, $profilePath); } return $profile; }
/** * @Flow\Around("method(Neos\Flow\Mvc\Routing\UriBuilder->uriFor())") * @param \Neos\Flow\Aop\JoinPointInterface $joinPoint The current join point * @return string The result of the target method if it has not been intercepted */ public function rewritePluginViewUris(JoinPointInterface $joinPoint) { /** @var ActionRequest $request */ $request = $joinPoint->getProxy()->getRequest(); $arguments = $joinPoint->getMethodArguments(); $currentNode = $request->getInternalArgument('__node'); if (!$request->getMainRequest()->hasArgument('node') || !$currentNode instanceof Node) { return $joinPoint->getAdviceChain()->proceed($joinPoint); } $currentNode = $request->getInternalArgument('__node'); $controllerObjectName = $this->getControllerObjectName($request, $arguments); $actionName = $arguments['actionName'] !== null ? $arguments['actionName'] : $request->getControllerActionName(); $targetNode = $this->pluginService->getPluginNodeByAction($currentNode, $controllerObjectName, $actionName); // TODO override namespace $q = new FlowQuery(array($targetNode)); $pageNode = $q->closest('[instanceof Neos.Neos:Document]')->get(0); $result = $this->generateUriForNode($request, $joinPoint, $pageNode); return $result; }
/** * Around advice, wrapping every method of a scope session object. It redirects * all method calls to the session object once there is one. * * @param JoinPointInterface $joinPoint The current join point * @return mixed * @Flow\Around("filter(Neos\Flow\Session\Aspect\SessionObjectMethodsPointcutFilter)") */ public function callMethodOnOriginalSessionObject(JoinPointInterface $joinPoint) { $objectName = $this->objectManager->getObjectNameByClassName(get_class($joinPoint->getProxy())); $methodName = $joinPoint->getMethodName(); $proxy = $joinPoint->getProxy(); if (!isset($this->sessionOriginalInstances[$objectName])) { $this->sessionOriginalInstances[$objectName] = $this->objectManager->get($objectName); } if ($this->sessionOriginalInstances[$objectName] === $proxy) { return $joinPoint->getAdviceChain()->proceed($joinPoint); } else { return call_user_func_array([$this->sessionOriginalInstances[$objectName], $methodName], $joinPoint->getMethodArguments()); } }
/** * Passes the signal over to the Dispatcher * * @Flow\AfterReturning("methodAnnotatedWith(Neos\Flow\Annotations\Signal)") * @param JoinPointInterface $joinPoint The current join point * @return void */ public function forwardSignalToDispatcher(JoinPointInterface $joinPoint) { $signalName = lcfirst(str_replace('emit', '', $joinPoint->getMethodName())); $this->dispatcher->dispatch($joinPoint->getClassName(), $signalName, $joinPoint->getMethodArguments()); }
/** * Determines the short or full class name of the session implementation * * @param JoinPointInterface $joinPoint * @return string */ protected function getClassName(JoinPointInterface $joinPoint) { $className = $joinPoint->getClassName(); $sessionNamespace = substr(SessionInterface::class, 0, -strrpos(SessionInterface::class, '\\') + 1); if (strpos($className, $sessionNamespace) === 0) { $className = substr($className, strlen($sessionNamespace)); } return $className; }
/** * Mark object as cloned after cloning. * * Note: this is not used by anything in the Flow base distribution, * but might be needed by custom backends (like Neos.CouchDB). * * @param JoinPointInterface $joinPoint * @return void * @Flow\AfterReturning("Neos\Flow\Persistence\Aspect\PersistenceMagicAspect->isEntityOrValueObject && method(.*->__clone())") */ public function cloneObject(JoinPointInterface $joinPoint) { $joinPoint->getProxy()->Flow_Persistence_clone = true; }
/** * Determines the short or full class name of the session implementation * * @param JoinPointInterface $joinPoint * @return string */ protected function getClassName(JoinPointInterface $joinPoint) { $className = $joinPoint->getClassName(); if (strpos($className, \Neos\Flow\Session::class) === 0) { $className = trim(substr($className, strlen(\Neos\Flow\Session::class)), '\\'); } return $className; }
/** * @Flow\AfterReturning("method(Neos\Flow\Tests\Functional\Aop\Fixtures\TargetClass02->publicTargetMethod())") * @param JoinPointInterface $joinPoint * @return string */ public function anAfterReturningAdvice(JoinPointInterface $joinPoint) { $joinPoint->getProxy()->afterReturningAdviceWasInvoked = true; }
/** * Logs calls and result of isPrivilegeTargetGranted() * * @Flow\After("method(Neos\Flow\Security\Authorization\PrivilegeManager->isPrivilegeTargetGranted())") * @param JoinPointInterface $joinPoint * @return void */ public function logPrivilegeAccessDecisions(JoinPointInterface $joinPoint) { $decision = $joinPoint->getResult() === true ? 'GRANTED' : 'DENIED'; $message = sprintf('Decided "%s" on privilege "%s".', $decision, $joinPoint->getMethodArgument('privilegeTargetIdentifier')); $this->securityLogger->log($message, \LOG_INFO); }