/**
  * Test whether singleton, session singleton, and application singleton caches
  * are not interfering. See issue ID#286 for details.
  */
 public function testCacheBoundaries()
 {
     $singletonCache = new ReflectionProperty(Singleton::class, 'CACHE');
     $singletonCache->setAccessible(true);
     $singletonCache->setValue(null, []);
     $sessionSingletonCache = new ReflectionProperty(SessionSingleton::class, 'CACHE');
     $sessionSingletonCache->setAccessible(true);
     $sessionSingletonCache->setValue(null, []);
     $applicationSingletonCache = new ReflectionProperty(ApplicationSingleton::class, 'CACHE');
     $applicationSingletonCache->setAccessible(true);
     $applicationSingletonCache->setValue(null, []);
     // test singleton instance is created in singleton cache only
     Singleton::getInstance(TagModel::class);
     $this->assertCount(1, $singletonCache->getValue(null));
     $this->assertCount(0, $sessionSingletonCache->getValue(null), 'Session singleton cache should be empty!');
     $this->assertCount(0, $applicationSingletonCache->getValue(null), 'Application singleton cache should be empty!');
     // test session singleton instance is created in singleton cache only
     SessionSingleton::getInstance(TagModel::class);
     $value = $singletonCache->getValue(null);
     $this->assertCount(2, $value);
     // 1=TagModel, 2=HttpRequestImpl (session singleton uses request -> session!)
     $this->assertEquals(TagModel::class, get_class($value[array_keys($value)[0]]));
     $this->assertEquals(RequestImpl::class, get_class($value[array_keys($value)[1]]));
     $this->assertCount(1, $sessionSingletonCache->getValue(null));
     $this->assertCount(0, $applicationSingletonCache->getValue(null), 'Application singleton cache should be empty!');
     // test application instance is created in singleton cache only
     ApplicationSingleton::getInstance(TagModel::class);
     $this->assertCount(2, $singletonCache->getValue(null));
     $this->assertCount(1, $sessionSingletonCache->getValue(null));
     $this->assertCount(1, $applicationSingletonCache->getValue(null));
 }
Example #2
0
 /**
  * Returns a service object according to the current application context.
  *
  * @param string $class Fully qualified class name of the service object.
  * @param string $context The application context, the service object belongs to.
  * @param string $language The language, the service object has.
  * @param array $arguments A list of constructor arguments to create the service instance with.
  * @param string $type The initializing type (see service manager for details).
  * @param string $instanceId The id of the instance to return.
  *
  * @return APFService The desired service object.
  * @throws InvalidArgumentException In case of invalid ServiceType or if requested service does not implement the APFService interface.
  *
  * @author Christian Schäfer
  * @version
  * Version 0.1, 07.03.2007<br />
  * Version 0.2, 17.03.2007 (Adjusted error messages)<br />
  * Version 0.3, 22.04.2007 (Language is now injected)<br />
  * Version 0.4, 24.02.2008 (Added SessionSingleton service type)<br />
  * Version 0.5, 25.02.2008 (Added performance optimization for the SessionSingleton objects)<br />
  * Version 0.6, 10.08.2009 (Added lazy import, so that the developer must not care about the inclusion of the component.)<br />
  * Version 0.7, 04.03.2011 (Refactored to static method; enhanced code)<br />
  * Version 0.8, 07.07.2012 Jan Wiese <*****@*****.**> (Corrected service retrieval to respect context and language each time.)<br />
  * Version 0.9, 23.07.2013 (Added "APPLICATIONSINGLETON" object creation mechanism.)<br />
  */
 public static function &getServiceObject($class, $context, $language, array $arguments = [], $type = APFService::SERVICE_TYPE_SINGLETON, $instanceId = null)
 {
     // Introduce generated instance key to create services with respect to the context.
     // In 1.15, creating instances of the same service implementation within different contexts
     // resulted in equal instances instead of different ones.
     // In 2.0 language has been removed from the instance id since within multi-language applications
     // you want to re-use the instance throughout different languages!
     if ($instanceId === null) {
         $instanceId = $class . '|' . $context;
     }
     $service = null;
     switch ($type) {
         case APFService::SERVICE_TYPE_SINGLETON:
             $service = Singleton::getInstance($class, $arguments, $instanceId);
             break;
         case APFService::SERVICE_TYPE_SESSION_SINGLETON:
             $service = SessionSingleton::getInstance($class, $arguments, $instanceId);
             break;
         case APFService::SERVICE_TYPE_APPLICATION_SINGLETON:
             $service = ApplicationSingleton::getInstance($class, $arguments, $instanceId);
             break;
         case APFService::SERVICE_TYPE_NORMAL:
             if (count($arguments) > 0) {
                 $service = (new ReflectionClass($class))->newInstanceArgs($arguments);
             } else {
                 $service = new $class();
             }
             break;
         default:
             throw new InvalidArgumentException('[ServiceManager::getServiceObject()] The given type (' . $type . ') is not supported. Please provide one out of "' . APFService::SERVICE_TYPE_SINGLETON . '", "' . APFService::SERVICE_TYPE_SESSION_SINGLETON . '" or "' . APFService::SERVICE_TYPE_NORMAL . '"', E_USER_WARNING);
     }
     // inject the basic set of information to the APF style service
     if ($service instanceof APFService) {
         $service->setContext($context);
         $service->setLanguage($language);
         $service->setServiceType($type);
     } else {
         throw new InvalidArgumentException('[ServiceManager::getServiceObject()] The precisely ' . 'now created object (' . $class . ') does not implement the APFService interface! ' . 'So context, language and service type cannot be set correctly!', E_USER_WARNING);
     }
     return $service;
 }
Example #3
0
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the APF. If not, see http://www.gnu.org/licenses/lgpl-3.0.txt.
 * -->
 */
namespace APF\core\singleton;

use APF\core\http\mixins\GetRequestResponse;
use APF\core\http\Session;
use APF\core\pagecontroller\APFObject;
use Exception;
use ReflectionClass;
// ID#178: use closure functions instead of [] to avoid issued with PHP 5.4.x
register_shutdown_function(function () {
    SessionSingleton::saveObjects();
});
/**
 * Implements the generic session singleton pattern. Can be used to create singleton objects
 * from every class. This eases unit tests, because explicit singleton implementations cause
 * side effects during unit testing. As a cache container, the $GLOBALS array is used.
 * <p/>
 * Session singleton objects remain valid throughout multiple requests and within one
 * sessions. They loose their validity when the session ends.
 * <p/>
 * Usage:
 * <pre>$myObject = SessionSingleton::getInstance('VENDOR\..\Class');</pre>
 *
 * @author Christian Schäfer
 * @version
 * Version 0.1, 24.02.2008<br />