/** * Logs calls * * @Flow\After("method(PerfectIn\Api\Webservice\WebserviceCall->invoke())") * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current joinpoint */ public function logFinishServiceCall(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { $callIdentifier = $joinPoint->getProxy()->getClass() . '::' . $joinPoint->getProxy()->getMethod(); if ($joinPoint->hasException()) { $this->logger->log($this->logIdentifier . ' - error - ' . $joinPoint->getException()->getMessage() . '(' . $joinPoint->getException()->getCode() . ')', LOG_ERR); } else { $this->logger->log($this->logIdentifier . ' - response - ' . $this->getLogMessageForVariable($joinPoint->getResult()), LOG_INFO); } }
/** * Around advice, wrapping every method of a scope session object. It redirects * all method calls to the session object once there is one. * * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current join point * @return mixed * @Flow\Around("filter(TYPO3\Flow\Session\Aspect\SessionObjectMethodsPointcutFilter)") */ public function callMethodOnOriginalSessionObject(\TYPO3\Flow\Aop\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(array($this->sessionOriginalInstances[$objectName], $methodName), $joinPoint->getMethodArguments()); } }
/** * @Flow\Before("method(TYPO3\Neos\Controller\Backend\ContentController->uploadAssetAction())") * @param JoinPointInterface $joinPoint The current join point * @return void */ public function rewriteSiteAssetCollection(JoinPointInterface $joinPoint) { if ($this->lookupNodeFilter === NULL || $this->lookupPropertyName === NULL) { return; } /** @var ContentController $contentController */ $contentController = $joinPoint->getProxy(); /** @var ActionRequest $actionRequest */ $actionRequest = ObjectAccess::getProperty($contentController, 'request', TRUE); $nodeContextPath = $actionRequest->getInternalArgument('__node'); if ($nodeContextPath === NULL) { return; } $node = $this->propertyMapper->convert($nodeContextPath, NodeInterface::class); $flowQuery = new FlowQuery(array($node)); /** @var NodeInterface $documentNode */ $documentNode = $flowQuery->closest($this->lookupNodeFilter)->get(0); if (!$documentNode->hasProperty($this->lookupPropertyName)) { return; } /** @var AssetCollection $assetCollection */ $assetCollection = $this->assetCollectionRepository->findByIdentifier($documentNode->getProperty($this->lookupPropertyName)); if ($assetCollection === NULL) { return; } /** @var Asset $asset */ $asset = $joinPoint->getMethodArgument('asset'); $assetCollection->addAsset($asset); $this->assetCollectionRepository->update($assetCollection); }
/** * 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 \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current join point * @return void * @Flow\Before("TYPO3\Flow\Persistence\Generic\Aspect\LazyLoadingObjectAspect->needsLazyLoadingObjectAspect && !method(.*->__construct())") */ public function initialize(\TYPO3\Flow\Aop\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); } }
/** * Add DQL function * * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current join point * @Flow\Before("method(TYPO3\Flow\Persistence\Doctrine\Service->runDql())") * @return void */ public function addDqlFunction(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { $entityManager = \TYPO3\Flow\Reflection\ObjectAccess::getProperty($joinPoint->getProxy(), 'entityManager', TRUE); $configuration = \TYPO3\Flow\Reflection\ObjectAccess::getProperty($entityManager, 'config', TRUE); $configuration->addCustomStringFunction('DAY', 'Lelesys\\Plugin\\News\\Doctrine\\Query\\Mysql\\Day'); $configuration->addCustomStringFunction('MONTH', 'Lelesys\\Plugin\\News\\Doctrine\\Query\\Mysql\\Month'); $configuration->addCustomStringFunction('YEAR', 'Lelesys\\Plugin\\News\\Doctrine\\Query\\Mysql\\Year'); }
/** * @param JoinPointInterface $joinPoint * @return mixed Result of the target method * @Flow\Around("class(TYPO3\Flow\Cli\Request) && method(.*->getCommand())") */ public function replaceCommandWithDomainCommand(JoinPointInterface $joinPoint) { /** @var Request $proxy */ $proxy = $joinPoint->getProxy(); if ($proxy->getControllerObjectName() === DomainCommandController::class) { ObjectAccess::setProperty($proxy, 'command', $this->buildDomainCommand($proxy->getControllerCommandName()), TRUE); } return $joinPoint->getAdviceChain()->proceed($joinPoint); }
/** * This changes how TagBuilder->addAttribute() method works. * When attribute's value is NULL or FALSE, it does *unset* the value. * Otherwise addAttribute() method is called as usually. * * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint * @Flow\Around("method(TYPO3\Fluid\Core\ViewHelper\TagBuilder->addAttribute())") * @return void */ public function catchAddAttribute(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { if (null === $joinPoint->getMethodArgument('attributeValue') || false === $joinPoint->getMethodArgument('attributeValue')) { /** @var \TYPO3\Fluid\Core\ViewHelper\TagBuilder $tagBuilder */ $tagBuilder = $joinPoint->getProxy(); $tagBuilder->removeAttribute($joinPoint->getMethodArgument('attributeName')); } else { $joinPoint->getAdviceChain()->proceed($joinPoint); } }
/** * @Flow\Around("method(Flowpack\Neos\FrontendLogin\Security\NeosRequestPattern->matchRequest())") * @param JoinPointInterface $joinPoint * @return boolean */ public function enhanceMatchRequest(JoinPointInterface $joinPoint) { $request = $joinPoint->getMethodArgument('request'); $requestPath = $request->getHttpRequest()->getUri()->getPath(); if ($joinPoint->getProxy()->getPattern() === NeosRequestPattern::PATTERN_BACKEND) { if (strpos($requestPath, '/che!') === 0) { return true; } } return $joinPoint->getAdviceChain()->proceed($joinPoint); }
/** * Advice for uncached segments when rendering from a cached version * * @Flow\AfterReturning("method(TYPO3\TypoScript\Core\Cache\RuntimeContentCache->evaluateUncached())") * @param JoinPointInterface $joinPoint */ public function registerEvaluateUncached(JoinPointInterface $joinPoint) { $path = $joinPoint->getMethodArgument('path'); $proxy = $joinPoint->getProxy(); /** @var Runtime $runtime */ $runtime = ObjectAccess::getProperty($proxy, 'runtime', TRUE); $mocVarnishIgnoreUncached = $runtime->evaluate($path . '/__meta/cache/mocVarnishIgnoreUncached'); if ($mocVarnishIgnoreUncached !== TRUE) { $this->evaluatedUncached = TRUE; } }
/** * Advice for uncached segments when rendering from a cached version * * @Flow\AfterReturning("method(TYPO3\TypoScript\Core\Cache\RuntimeContentCache->evaluateUncached())") * @param JoinPointInterface $joinPoint */ public function registerEvaluateUncached(JoinPointInterface $joinPoint) { $path = $joinPoint->getMethodArgument('path'); $proxy = $joinPoint->getProxy(); /** @var Runtime $runtime */ $runtime = ObjectAccess::getProperty($proxy, 'runtime', TRUE); $mocVarnishIgnoreUncached = $runtime->evaluate($path . '/__meta/cache/mocVarnishIgnoreUncached'); if ($mocVarnishIgnoreUncached !== TRUE) { $this->logger->log(sprintf('Varnish cache disabled due to uncached path "%s" (can be prevented using "mocVarnishIgnoreUncached")', $path . '/__meta/cache/mocVarnishIgnoreUncached'), LOG_DEBUG); $this->evaluatedUncached = TRUE; } }
/** * @Flow\AfterReturning("method(TYPO3\Flow\Security\Account->authenticationAttempted())") * @param JoinPointInterface $joinPoint * @return void */ public function bruteForceAccountLocking(JoinPointInterface $joinPoint) { $failedAttemptsThreshold = intval($this->settings['failedAttemptsThreshold']); if ($failedAttemptsThreshold === 0) { return; } /** @var \TYPO3\Flow\Security\Account $account */ $account = $joinPoint->getProxy(); // Deactivate account if failed attempts exceed threshold if ($account->getFailedAuthenticationCount() >= $failedAttemptsThreshold) { $account->setExpirationDate(new \DateTime()); $this->sendNotificationMail($account); } }
/** * @param JoinPointInterface $joinPoint * @Flow\After("method(TYPO3\TypoScript\Core\Runtime->pushContextArray())") * @return void */ public function extendContextWithMetaDataRootNode(JoinPointInterface $joinPoint) { /** @var \TYPO3\TypoScript\Core\Runtime $runtime */ $runtime = $joinPoint->getProxy(); $currentContext = $runtime->getCurrentContext(); if (isset($currentContext['node'])) { /** @var \TYPO3\TYPO3CR\Domain\Model\NodeInterface $node */ $node = $currentContext['node']; $metaDataRootNode = $this->nodeService->findOrCreateMetaDataRootNode($node->getContext()); $currentContext = $runtime->popContext(); $currentContext[MetaDataRepository::METADATA_ROOT_NODE_NAME] = $metaDataRootNode; $runtime->pushContextArray($currentContext); } }
/** * @Flow\Around("setting(Ttree.Embedly.logApiRequest) && within(Ttree\Embedly\Embedly) && method(public .*->(oembed|preview|objectify|extract|services)())") * @param JoinPointInterface $joinPoint The current join point * @return mixed */ public function getResponseFromCache(JoinPointInterface $joinPoint) { $proxy = $joinPoint->getProxy(); $key = ObjectAccess::getProperty($proxy, 'key'); $params = $joinPoint->getMethodArgument('params'); $cacheKey = md5($joinPoint->getClassName() . $joinPoint->getMethodName() . $key . json_encode($params)); if ($this->responseCache->has($cacheKey)) { $this->systemLogger->log(sprintf(' cache hit Embedly::%s', $joinPoint->getMethodName()), LOG_DEBUG); return $this->responseCache->get($cacheKey); } else { $this->systemLogger->log(sprintf(' cache miss Embedly::%s', $joinPoint->getMethodName()), LOG_DEBUG); } $response = $joinPoint->getAdviceChain()->proceed($joinPoint); $this->responseCache->set($cacheKey, $response); return $response; }
/** * Logs calls and results of the logout() method of the Authentication Manager * * @Flow\AfterReturning("within(TYPO3\Flow\Security\Authentication\AuthenticationManagerInterface) && method(.*->logout())") * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current joinpoint * @return mixed The result of the target method if it has not been intercepted */ public function logManagerLogout(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { /** @var $securityContext \TYPO3\Flow\Security\Context */ $securityContext = $joinPoint->getProxy()->getSecurityContext(); if (!$securityContext->isInitialized()) { return; } $accountIdentifiers = array(); foreach ($securityContext->getAuthenticationTokens() as $token) { /** @var $account \TYPO3\Flow\Security\Account */ $account = $token->getAccount(); if ($account !== NULL) { $accountIdentifiers[] = $account->getAccountIdentifier(); } } $this->securityLogger->log('Logged out ' . count($accountIdentifiers) . ' account(s). (' . implode(', ', $accountIdentifiers) . ')', LOG_INFO); }
/** * Logs calls and results of the logout() method of the Authentication Manager * * @Flow\AfterReturning("within(TYPO3\Flow\Security\Authentication\AuthenticationManagerInterface) && method(.*->logout())") * @param JoinPointInterface $joinPoint The current joinpoint * @return mixed The result of the target method if it has not been intercepted */ public function logManagerLogout(JoinPointInterface $joinPoint) { /** @var AuthenticationManagerInterface $authenticationManager */ $authenticationManager = $joinPoint->getProxy(); $securityContext = $authenticationManager->getSecurityContext(); if (!$securityContext->isInitialized()) { return; } $accountIdentifiers = array(); foreach ($securityContext->getAuthenticationTokens() as $token) { /** @var $account Account */ $account = $token->getAccount(); if ($account !== null) { $accountIdentifiers[] = $account->getAccountIdentifier(); } } $this->securityLogger->log(sprintf('Logged out %d account(s). (%s)', count($accountIdentifiers), implode(', ', $accountIdentifiers)), LOG_INFO); }
/** * @Flow\Around("method(TYPO3\Flow\Mvc\Routing\UriBuilder->uriFor())") * @param \TYPO3\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 \TYPO3\Flow\Mvc\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 TYPO3.Neos:Document]')->get(0); $result = $this->generateUriForNode($request, $joinPoint, $pageNode); return $result; }
/** * Sets the request format according th the given accept header. * * @Flow\After("method(TYPO3\Flow\Mvc\ActionRequest->setArguments())") * @param JoinPointInterface $joinPoint The current joinpoint */ public function setRequestFormatByAcceptHeader(JoinPointInterface $joinPoint) { /** @var \TYPO3\Flow\Mvc\ActionRequest $actionRequest */ $actionRequest = $joinPoint->getProxy(); /** * The Accept header should be the only one to determine which resulting * data format the client is able to understand. But since some JS libs * do send Accept XML but Content-Type Json even when the expect to process * jsonapi.org format data we care about both, the Accept header as well * as the Content-Type header. */ foreach (array('Accept', 'Http-Accept', 'Content-Type') as $fieldName) { $headerValue = $actionRequest->getHttpRequest()->getHeader($fieldName); foreach (array('application/json', 'application/vnd.api+json') as $acceptableValue) { if (strpos($headerValue, $acceptableValue) !== false) { $actionRequest->setFormat('json'); return; } } } }
/** * 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 TYPO3.CouchDB). * * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint * @return void * @Flow\AfterReturning("TYPO3\Flow\Persistence\Aspect\PersistenceMagicAspect->isEntityOrValueObject && method(.*->__clone())") */ public function cloneObject(JoinPointInterface $joinPoint) { $joinPoint->getProxy()->Flow_Persistence_clone = true; }
/** * @Flow\AfterReturning("method(TYPO3\Flow\Tests\Functional\Aop\Fixtures\TargetClass02->publicTargetMethod())") * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint * @return string */ public function anAfterReturningAdvice(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { $joinPoint->getProxy()->afterReturningAdviceWasInvoked = TRUE; }
/** * @Flow\AfterReturning("method(TYPO3\Neos\Domain\Service\ContentContext->__construct())") * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current join point * @return void */ public function retrieveContentContext(JoinPointInterface $joinPoint) { if ($this->contentContextContainer->isInitialized()) { $this->contentContextContainer->initializeContentContext($joinPoint->getProxy()); } }
/** * * @Flow\After("method(TYPO3\Flow\Mvc\Routing\Route->matches(*))") * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current join point * @return array Result of the target method */ public function logRoutes(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { $route = $joinPoint->getProxy(); \Debug\Toolbar\Service\DataStorage::add('Route:Routes', $route->getUriPattern()); }
/** * Logs calls of renewId() * * @Flow\Around("within(TYPO3\Flow\Session\SessionInterface) && method(.*->renewId())") * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current joinpoint * @return mixed The result of the target method if it has not been intercepted */ public function logRenewId(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { $session = $joinPoint->getProxy(); $oldId = $session->getId(); $newId = $joinPoint->getAdviceChain()->proceed($joinPoint); if ($session->isStarted()) { $this->systemLogger->log(sprintf('%s: Changed session id from %s to %s', $this->getClassName($joinPoint), $oldId, $newId), LOG_INFO); } return $newId; }
/** * Set new template for paginator * * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current join point * @Flow\Before("method(TYPO3\Fluid\ViewHelpers\Widget\Controller\PaginateController->indexAction())") * @return void */ public function setPaginationTemplate(\TYPO3\Flow\Aop\JoinPointInterface $joinPoint) { $paginateController = $joinPoint->getProxy(); $view = \TYPO3\Flow\Reflection\ObjectAccess::getProperty($paginateController, 'view', TRUE); $view->setTemplatePathAndFilename($this->settings['paginateTemplatePath']); }
/** * Flow 3.x * * @Flow\AfterReturning("method(TYPO3\Flow\Resource\Target\FileSystemSymlinkTarget->publishFile())") * @Flow\AfterReturning("method(TYPO3\Flow\Resource\Target\FileSystemTarget->publishFile())") * @param \TYPO3\Flow\Aop\JoinPointInterface $joinPoint The current join point * @return void */ public function optimizePublishedFile(JoinPointInterface $joinPoint) { $proxy = $joinPoint->getProxy(); $path = ObjectAccess::getProperty($proxy, 'path', TRUE); $this->optimizeFile($path . $joinPoint->getMethodArgument('relativeTargetPathAndFilename')); }
/** * This aspect will block loadNodeTypes from being called and will instead * call overrideNodeTypes with a modified configuration. * * @Flow\Around("method(TYPO3\TYPO3CR\Domain\Service\NodeTypeManager->loadNodeTypes())") * @param JoinPointInterface $joinPoint The current join point * @return void */ public function addDynamicNodeConfiguration(JoinPointInterface $joinPoint) { $completeNodeTypeConfiguration = $this->configurationManager->getConfiguration('NodeTypes'); $dynamicNodeTypes = $this->dynamicNodeTypeRepository->findAll(); /* @var $dynamicNodeType DynamicNodeType */ foreach ($dynamicNodeTypes as $dynamicNodeType) { $dynamicNodeName = $dynamicNodeType->getValidNodeTypeName($this->settings['nodeNamespace']); if (!array_key_exists($dynamicNodeName, $completeNodeTypeConfiguration)) { $dynamicProperties = array(); /* @var $dynamicProperty DynamicProperty */ foreach ($dynamicNodeType->getDynamicProperties() as $dynamicProperty) { $dynamicPropertyName = $dynamicProperty->getValidPropertyName($this->settings['propertyPrefix']); $dynamicProperties[$dynamicPropertyName] = array('type' => 'string', 'defaultValue' => $dynamicProperty->getDefaultValue(), 'ui' => array('label' => $dynamicProperty->getLabel(), 'reloadIfChanged' => TRUE, 'inlineEditable' => TRUE, 'aloha' => array('placeholder' => $dynamicProperty->getPlaceholder()), 'inspector' => array('group' => 'dynamicProperties', 'editorOptions' => array('placeholder' => $dynamicProperty->getPlaceholder())))); } $newNodeConfiguration = array('superTypes' => $this->settings['superTypes'], 'abstract' => FALSE, 'ui' => array('label' => $dynamicNodeType->getLabel())); // Only set properties if there are any. // If properties is set to an empty array a bug in Neos will break the node configuration. // This leads to an empty inspector and strange error messages. if (count($dynamicProperties)) { $newNodeConfiguration['properties'] = $dynamicProperties; } $completeNodeTypeConfiguration[$dynamicNodeName] = $newNodeConfiguration; } } /* @var $nodeTypeManager NodeTypeManager */ $nodeTypeManager = $joinPoint->getProxy(); $nodeTypeManager->overrideNodeTypes($completeNodeTypeConfiguration); }