예제 #1
0
 /**
  * Flushes entries tagged by the specified tag of all registered
  * caches.
  *
  * @param string $tag Tag to search for
  * @return void
  * @author Robert Lemke <*****@*****.**>
  * @api
  */
 public function flushCachesByTag($tag)
 {
     $this->systemLogger->log(sprintf('Flushing caches by tag "%s".', $tag), LOG_DEBUG);
     foreach ($this->caches as $cache) {
         $cache->flushByTag($tag);
     }
 }
예제 #2
0
 /**
  * Detects changes of the files and directories to be monitored and emits signals
  * accordingly.
  *
  * @return void
  * @author Robert Lemke <*****@*****.**>
  * @api
  */
 public function detectChanges()
 {
     $changedFiles = array();
     $changedDirectories = array();
     $changedFiles = $this->detectChangedFiles($this->monitoredFiles);
     foreach ($this->monitoredDirectories as $path) {
         if (!isset($this->directoriesAndFiles[$path])) {
             $this->directoriesAndFiles[$path] = \F3\FLOW3\Utility\Files::readDirectoryRecursively($path);
             $this->directoriesChanged = TRUE;
             $changedDirectories[$path] = \F3\FLOW3\Monitor\ChangeDetectionStrategy\ChangeDetectionStrategyInterface::STATUS_CREATED;
         }
     }
     foreach ($this->directoriesAndFiles as $path => $pathAndFilenames) {
         if (!is_dir($path)) {
             unset($this->directoriesAndFiles[$path]);
             $this->directoriesChanged = TRUE;
             $changedDirectories[$path] = \F3\FLOW3\Monitor\ChangeDetectionStrategy\ChangeDetectionStrategyInterface::STATUS_DELETED;
         } else {
             $currentSubDirectoriesAndFiles = \F3\FLOW3\Utility\Files::readDirectoryRecursively($path);
             if ($currentSubDirectoriesAndFiles != $pathAndFilenames) {
                 $pathAndFilenames = array_unique(array_merge($currentSubDirectoriesAndFiles, $pathAndFilenames));
             }
             $changedFiles = array_merge($changedFiles, $this->detectChangedFiles($pathAndFilenames));
         }
     }
     if (count($changedFiles) > 0) {
         $this->emitFilesHaveChanged($this->identifier, $changedFiles);
     }
     if (count($changedDirectories) > 0) {
         $this->emitDirectoriesHaveChanged($this->identifier, $changedDirectories);
     }
     if (count($changedFiles) > 0 || count($changedDirectories) > 0) {
         $this->systemLogger->log(sprintf('File Monitor detected %s changed files and %s changed directories.', count($changedFiles), count($changedDirectories)), LOG_INFO);
     }
 }
예제 #3
0
 /**
  * Dispatches a signal by calling the registered Slot methods
  *
  * @param string $signalClassName Name of the class containing the signal
  * @param string $signalMethodName Method name of the signal
  * @param array $signalArguments arguments passed to the signal method
  * @return void
  * @throws \F3\FLOW3\SignalSlot\Exception\InvalidSlotException if the slot is not valid
  * @author Robert Lemke <*****@*****.**>
  * @api
  */
 public function dispatch($signalClassName, $signalMethodName, array $signalArguments)
 {
     if (!isset($this->slots[$signalClassName][$signalMethodName])) {
         return;
     }
     $this->systemLogger->log(sprintf('Dispatching signal %s::%s ...', $signalClassName, $signalMethodName), LOG_DEBUG);
     foreach ($this->slots[$signalClassName][$signalMethodName] as $slotInformation) {
         if (isset($slotInformation['object'])) {
             $object = $slotInformation['object'];
         } else {
             if (!$this->objectManager->isObjectRegistered($slotInformation['class'])) {
                 throw new \F3\FLOW3\SignalSlot\Exception\InvalidSlotException('The given class "' . $slotInformation['class'] . '" is not a registered object.', 1245673367);
             }
             $object = $this->objectManager->getObject($slotInformation['class']);
         }
         $slotArguments = $signalArguments;
         if ($slotInformation['omitSignalInformation'] !== TRUE) {
             array_unshift($slotArguments, $signalClassName . '::' . $signalMethodName);
         }
         $this->systemLogger->log(sprintf('  to slot %s::%s.', get_class($object), $slotInformation['method']), LOG_DEBUG);
         if (!method_exists($object, $slotInformation['method'])) {
             throw new \F3\FLOW3\SignalSlot\Exception\InvalidSlotException('The slot method ' . get_class($object) . '->' . $slotInformation['method'] . '() does not exist.', 1245673368);
         }
         call_user_func_array(array($object, $slotInformation['method']), $slotArguments);
     }
 }
예제 #4
0
 /**
  * Does garbage collection
  *
  * @return void
  * @author Karsten Dambekalns <*****@*****.**>
  * @api
  */
 public function collectGarbage()
 {
     $statementHandle = $this->databaseHandle->prepare('DELETE FROM "tags" WHERE "scope"=? AND "cache"=? AND "identifier" IN (SELECT "identifier" FROM "cache" WHERE "scope"=? AND "cache"=? AND "lifetime" > 0 AND "created" + "lifetime" < ' . time() . ')');
     $statementHandle->execute(array($this->scope, $this->cacheIdentifier, $this->scope, $this->cacheIdentifier));
     $statementHandle = $this->databaseHandle->prepare('DELETE FROM "cache" WHERE "scope"=? AND "cache"=? AND "lifetime" > 0 AND "created" + "lifetime" < ' . time());
     $statementHandle->execute(array($this->scope, $this->cacheIdentifier));
     $this->systemLogger->log(sprintf('Cache %s: removed %s entries during garbage collection', $this->cacheIdentifier, $statementHandle->rowCount()), LOG_INFO);
 }
 /**
  * Handles the given exception
  *
  * @param \Exception $exception The exception object
  * @return void
  */
 public function handleException(\Exception $exception)
 {
     if (is_object($this->systemLogger)) {
         $exceptionCodeNumber = $exception->getCode() > 0 ? ' #' . $exception->getCode() : '';
         $backTrace = $exception->getTrace();
         $className = isset($backTrace[0]['class']) ? $backTrace[0]['class'] : '?';
         $methodName = isset($backTrace[0]['function']) ? $backTrace[0]['function'] : '?';
         $line = isset($backTrace['line']) ? ' in line ' . $backTrace['line'] : '';
         $message = 'Uncaught exception' . $exceptionCodeNumber . '. ' . $exception->getMessage() . $line . '.';
         $explodedClassName = explode('\\', $className);
         $packageKey = isset($explodedClassName[1]) ? $explodedClassName[1] : NULL;
         $this->systemLogger->log($message, LOG_CRIT, array(), $packageKey, $className, $methodName);
     }
     if (is_object($this->lockManager)) {
         $this->lockManager->unlockSite();
     }
 }
예제 #6
0
 /**
  * Builds the corresponding uri (excluding protocol and host) by iterating
  * through all configured routes and calling their respective resolves()
  * method. If no matching route is found, an empty string is returned.
  * Note: calls of this message are cached by RouterCachingAspect
  *
  * @param array $routeValues Key/value pairs to be resolved. E.g. array('@package' => 'MyPackage', '@controller' => 'MyController');
  * @return string
  * @author Bastian Waidelich <*****@*****.**>
  */
 public function resolve(array $routeValues)
 {
     $this->createRoutesFromConfiguration();
     foreach ($this->routes as $route) {
         if ($route->resolves($routeValues)) {
             return $route->getMatchingUri();
         }
     }
     $this->systemLogger->log('Router resolve(): No route matched ' . str_replace(chr(10), '', var_export($routeValues, TRUE)) . '.', LOG_NOTICE);
     return '';
 }
예제 #7
0
 /**
  * Unlocks the site if this request has locked it.
  *
  * @return void
  * @author Robert Lemke <*****@*****.**>
  * @api
  */
 public function unlockSite()
 {
     if ($this->siteLocked === TRUE) {
         if (file_exists($this->lockPathAndFilename)) {
             unlink($this->lockPathAndFilename);
         } else {
             $this->systemLogger->log('Site is locked but no lockfile could be found.', LOG_WARNING);
         }
         $this->siteLocked = FALSE;
         $this->systemLogger->log('Unlocked site.', LOG_NOTICE);
     }
 }
예제 #8
0
 /**
  * Does garbage collection
  *
  * @return void
  * @author Karsten Dambekalns <*****@*****.**>
  * @api
  */
 public function collectGarbage()
 {
     if (!$this->cache instanceof \F3\FLOW3\Cache\Frontend\FrontendInterface) {
         throw new \F3\FLOW3\Cache\Exception('Yet no cache frontend has been set via setCache().', 1222686150);
     }
     $pattern = $this->cacheDirectory . 'Data/' . $this->cacheIdentifier . '/*/*/*';
     $filesFound = glob($pattern);
     foreach ($filesFound as $cacheFilename) {
         if ($this->isCacheFileExpired($cacheFilename)) {
             $this->remove(basename($cacheFilename));
         }
     }
     $this->systemLogger->log(sprintf('Cache %s: removed %s files during garbage collection', $this->cacheIdentifier, count($filesFound)), LOG_INFO);
 }
 /**
  * Logs calls and results of the authenticate() method of the PersistedUsernamePasswordProvider Authentication Provider
  *
  * @afterreturning method(F3\FLOW3\Security\Authentication\Provider\PersistedUsernamePasswordProvider->authenticate())
  * @param \F3\FLOW3\AOP\JoinPointInterface $joinPoint The current joinpoint
  * @return mixed The result of the target method if it has not been intercepted
  * @author Robert Lemke <*****@*****.**>
  */
 public function logPersistedUsernamePasswordProviderAuthenticate(\F3\FLOW3\AOP\JoinPointInterface $joinPoint)
 {
     $token = $joinPoint->getMethodArgument('authenticationToken');
     $credentials = $token->getCredentials();
     switch ($token->getAuthenticationStatus()) {
         case \F3\FLOW3\Security\Authentication\TokenInterface::AUTHENTICATION_SUCCESSFUL:
             $this->systemLogger->log('Successfully authenticated user "' . $credentials['username'] . '".', LOG_INFO, array(), 'FLOW3', 'F3\\FLOW3\\Security\\Authentication\\Provider\\PersistedUsernamePasswordProvider', 'authenticate');
             break;
         case \F3\FLOW3\Security\Authentication\TokenInterface::WRONG_CREDENTIALS:
             $this->systemLogger->log('Wrong password given for user "' . $credentials['username'] . '".', LOG_WARNING, array(), 'FLOW3', 'F3\\FLOW3\\Security\\Authentication\\Provider\\PersistedUsernamePasswordProvider', 'authenticate');
             break;
         case \F3\FLOW3\Security\Authentication\TokenInterface::NO_CREDENTIALS_GIVEN:
             $this->systemLogger->log('No credentials given or no account found with username "' . $credentials['username'] . '".', LOG_WARNING, array(), 'FLOW3', 'F3\\FLOW3\\Security\\Authentication\\Provider\\PersistedUsernamePasswordProvider', 'authenticate');
             break;
     }
 }
예제 #10
0
 /**
  * Creates FLOW3's temporary directory - or at least asserts that it exists and is
  * writable.
  *
  * @param string $temporaryDirectoryBase Full path to the base for the temporary directory
  * @return string The full path to the temporary directory
  * @throws \F3\FLOW3\Utility\Exception if the temporary directory could not be created or is not writable
  * @author Robert Lemke <*****@*****.**>
  * @author Bastian Waidelich <*****@*****.**>
  */
 protected function createTemporaryDirectory($temporaryDirectoryBase)
 {
     $temporaryDirectoryBase = \F3\FLOW3\Utility\Files::getUnixStylePath($temporaryDirectoryBase);
     if (substr($temporaryDirectoryBase, -1, 1) !== '/') {
         $temporaryDirectoryBase .= '/';
     }
     $maximumPathLength = $this->getMaximumPathLength();
     if (strlen($temporaryDirectoryBase) > $maximumPathLength - 230) {
         $this->systemLogger->log('The path to your temporary directory is ' . strlen($temporaryDirectoryBase) . ' characters long. The maximum path length of your system is only ' . $maximumPathLength . '. Please consider setting the temporaryDirectoryBase option to a shorter path.', LOG_WARNING);
     }
     $processUser = extension_loaded('posix') ? posix_getpwuid(posix_geteuid()) : array('name' => 'default');
     $pathHash = substr(md5(FLOW3_PATH_WEB . $this->getSAPIName() . $processUser['name'] . $this->context), 0, 12);
     $temporaryDirectory = $temporaryDirectoryBase . $pathHash . '/';
     if (!is_dir($temporaryDirectory)) {
         try {
             \F3\FLOW3\Utility\Files::createDirectoryRecursively($temporaryDirectory);
         } catch (\F3\FLOW3\Error\Exception $exception) {
         }
     }
     if (!is_writable($temporaryDirectory)) {
         throw new \F3\FLOW3\Utility\Exception('The temporary directory "' . $temporaryDirectory . '" could not be created or is not writable for the current user "' . $processUser['name'] . '". Please make this directory writable or define another temporary directory by setting the respective system environment variable (eg. TMPDIR) or defining it in the FLOW3 settings.', 1216287176);
     }
     return $temporaryDirectory;
 }
예제 #11
0
 /**
  * Runs the the FLOW3 Framework by resolving an appropriate Request Handler and passing control to it.
  * If the Framework is not initialized yet, it will be initialized.
  *
  * @return void
  * @author Robert Lemke <*****@*****.**>
  * @api
  */
 public function run()
 {
     if (!$this->siteLocked) {
         $requestHandlerResolver = $this->objectManager->getObject('F3\\FLOW3\\MVC\\RequestHandlerResolver');
         $requestHandler = $requestHandlerResolver->resolveRequestHandler();
         $requestHandler->handleRequest();
         if ($this->settings['persistence']['enable'] === TRUE) {
             $this->objectManager->getObject('F3\\FLOW3\\Persistence\\ManagerInterface')->persistAll();
         }
         $this->emitFinishedNormalRun();
         $this->systemLogger->log('Shutting down ...', LOG_INFO);
         $this->configurationManager->shutdown();
         $this->objectManager->shutdown();
         $this->reflectionService->shutdown();
         $this->objectManager->getObject('F3\\FLOW3\\Object\\SessionRegistry')->writeDataToSession();
         $this->objectManager->getObject('F3\\FLOW3\\Session\\SessionInterface')->close();
     } else {
         header('HTTP/1.1 503 Service Temporarily Unavailable');
         readfile('package://FLOW3/Private/Core/LockHoldingStackPage.html');
         $this->systemLogger->log('Site is locked, exiting.', LOG_NOTICE);
     }
 }
 /**
  * Writes the given message along with the additional information into the log.
  *
  * @param string $message The message to log
  * @param integer $severity An integer value, one of the SEVERITY_* constants
  * @param mixed $additionalData A variable containing more information about the event to be logged
  * @return void
  * @author Robert Lemke <*****@*****.**>
  */
 protected function log($message, $severity = 6, $additionalData = NULL)
 {
     if (is_object($this->systemLogger)) {
         $this->systemLogger->log($message, $severity, $additionalData);
     }
 }
예제 #13
0
 /**
  * Initializes the AOP framework.
  *
  * During initialization the specified configuration of objects is searched for possible
  * aspect annotations. If an aspect class is found, the poincut expressions are parsed and
  * a new aspect with one or more advisors is added to the aspect registry of the AOP framework.
  * Finally all advices are woven into their target classes by generating proxy classes.
  *
  * The class names of all proxied classes is stored back in the $objectConfigurations array.
  *
  * @param array &$objectConfigurations
  * @return void
  * @author Robert Lemke <*****@*****.**>
  */
 public function initialize(array &$objectConfigurations)
 {
     if ($this->isInitialized) {
         throw new \F3\FLOW3\AOP\Exception('The AOP framework has already been initialized!', 1169550994);
     }
     $this->isInitialized = TRUE;
     if ($this->proxyBuildInformationCache->has('targetAndProxyClassNames')) {
         $this->targetAndProxyClassNames = $this->proxyBuildInformationCache->get('targetAndProxyClassNames');
     }
     if (!$this->proxyBuildInformationCache->has('allProxyClassesUpToDate')) {
         $allAvailableClassNames = $this->getAllImplementationClassesFromObjectConfigurations($objectConfigurations);
         $cachedTargetClassNames = $this->proxyBuildInformationCache->has('targetClassNames') ? $this->proxyBuildInformationCache->get('targetClassNames') : array();
         $cachedAspectClassNames = $this->proxyBuildInformationCache->has('aspectClassNames') ? $this->proxyBuildInformationCache->get('aspectClassNames') : array();
         $actualTargetClassNames = $this->getProxyableClasses($allAvailableClassNames);
         $actualAspectClassNames = $this->reflectionService->getClassNamesByTag('aspect');
         sort($actualTargetClassNames);
         sort($actualAspectClassNames);
         $this->aspectContainers = $this->buildAspectContainers($allAvailableClassNames);
         $dirtyTargetClassNames = $actualTargetClassNames;
         if ($cachedAspectClassNames === $actualAspectClassNames) {
             $validProxyClassesCount = 0;
             $outdatedProxyClassesCount = 0;
             foreach ($this->targetAndProxyClassNames as $targetClassName => $proxyClassName) {
                 if ($this->proxyClassesCache->has(str_replace('\\', '_', $proxyClassName))) {
                     $validProxyClassesCount++;
                     $dirtyTargetClassNames = array_diff($dirtyTargetClassNames, array($targetClassName));
                 } else {
                     $outdatedProxyClassesCount++;
                     unset($this->targetAndProxyClassNames[$targetClassName]);
                 }
             }
             $this->systemLogger->log(sprintf('At least one target class changed, aspects unchanged. Found %s valid and %s outdated proxy classes.', $validProxyClassesCount, $outdatedProxyClassesCount), LOG_INFO);
         } else {
             $this->systemLogger->log(sprintf('At least one aspect changed, rebuilding proxy classes for %s target classes.', count($actualTargetClassNames)), LOG_INFO);
             $this->proxyClassesCache->flush();
             $this->targetAndProxyClassNames = array();
         }
         foreach ($dirtyTargetClassNames as $targetClassName) {
             $proxyBuildResult = $this->proxyClassBuilder->buildProxyClass($targetClassName, $this->aspectContainers, $this->objectManager->getContext());
             if ($proxyBuildResult !== FALSE) {
                 $this->targetAndProxyClassNames[$targetClassName] = $proxyBuildResult['proxyClassName'];
                 $this->systemLogger->log(sprintf('Built proxy class "%s" for target class "%s" (length: %s).', $proxyBuildResult['proxyClassName'], $targetClassName, strlen($proxyBuildResult['proxyClassCode'])), LOG_DEBUG);
                 $this->proxyClassesCache->set(str_replace('\\', '_', $proxyBuildResult['proxyClassName']), $proxyBuildResult['proxyClassCode'], array($this->proxyClassesCache->getClassTag($targetClassName)));
             } else {
                 unset($this->targetAndProxyClassNames[$targetClassName]);
             }
         }
         $aspectClassesTags = array();
         foreach ($actualAspectClassNames as $aspectClassName) {
             $aspectClassesTags[] = $this->proxyBuildInformationCache->getClassTag($aspectClassName);
         }
         $this->proxyBuildInformationCache->set('targetAndProxyClassNames', $this->targetAndProxyClassNames);
         $this->proxyBuildInformationCache->set('aspectClassNames', $actualAspectClassNames, $aspectClassesTags);
         $this->proxyBuildInformationCache->set('targetClassNames', $actualTargetClassNames);
         $this->proxyBuildInformationCache->set('allProxyClassesUpToDate', '', array($this->proxyClassesCache->getClassTag()));
     }
     foreach ($this->targetAndProxyClassNames as $targetClassName => $proxyClassName) {
         if (class_exists($proxyClassName, FALSE)) {
             throw new \F3\FLOW3\AOP\Exception('Class ' . $proxyClassName . ' already exists.', 1229361833);
         }
         if (!$this->proxyClassesCache->has(str_replace('\\', '_', $proxyClassName))) {
             throw new \F3\FLOW3\AOP\Exception('No proxy class code for class "' . $proxyClassName . '" found in cache.', 1229362833);
         }
         $this->proxyClassesCache->requireOnce(str_replace('\\', '_', $proxyClassName));
         foreach ($objectConfigurations as $objectName => $objectConfiguration) {
             if ($objectConfiguration->getClassName() === $targetClassName) {
                 $objectConfigurations[$objectName]->setClassName($proxyClassName);
             }
         }
     }
 }
 /**
  * Does nothing, as memcached does GC itself
  *
  * @return void
  * @api
  */
 public function collectGarbage()
 {
     $this->systemLogger->log(sprintf('Cache %s: garbage collection is done by memcached', $this->cacheIdentifier), LOG_INFO);
 }