Overview

Namespaces

  • Faulancer
    • Controller
    • Exception
    • Form
      • Validator
        • Type
    • Helper
      • Reflection
    • Http
    • Mail
    • ORM
      • User
    • Service
      • Factory
    • ServiceLocator
    • Session
    • View
      • Helper

Classes

  • ServiceLocator

Interfaces

  • FactoryInterface
  • ServiceInterface
  • ServiceLocatorInterface
  • Overview
  • Namespace
  • Class
  1:   2:   3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13:  14:  15:  16:  17:  18:  19:  20:  21:  22:  23:  24:  25:  26:  27:  28:  29:  30:  31:  32:  33:  34:  35:  36:  37:  38:  39:  40:  41:  42:  43:  44:  45:  46:  47:  48:  49:  50:  51:  52:  53:  54:  55:  56:  57:  58:  59:  60:  61:  62:  63:  64:  65:  66:  67:  68:  69:  70:  71:  72:  73:  74:  75:  76:  77:  78:  79:  80:  81:  82:  83:  84:  85:  86:  87:  88:  89:  90:  91:  92:  93:  94:  95:  96:  97:  98:  99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 
<?php
/**
 * Class ServiceLocator | ServiceLocator.php
 *
 * @package Faulancer\ServiceLocator
 * @author Florian Knapp <office@florianknapp.de>
 */
namespace Faulancer\ServiceLocator;

use Faulancer\Exception\FactoryMayIncompatibleException;
use Faulancer\Exception\ServiceNotFoundException;

/**
 * Class ServiceLocator
 */
class ServiceLocator implements ServiceLocatorInterface {

    /**
     * Holds the service locator instance
     * @var ServiceLocator
     */
    private static $instance = null;

    /**
     * Holds the requested services
     * @var array
     */
    private static $services = [];

    /** @var array */
    private static $backup = [];

    /**
     * ServiceLocator private constructor.
     */
    private function __construct() {}

    /**
     * Return the instance of the service locator
     * @return ServiceLocator
     */
    public static function instance()
    {
        if (self::$instance === null) {
            self::$instance = new self;
        }

        return self::$instance;
    }

    /**
     * Try to get the service.
     * Returns per default always a new instance of the service/factory.
     *
     * @param string  $service
     * @param boolean $shared
     * @return ServiceInterface|FactoryInterface
     * @throws ServiceNotFoundException
     */
    public function get(string $service = '', $shared = true)
    {
        if (in_array($service, array_keys(self::$backup))) {

            $overriddenService = self::$services[$service];
            self::$services[$service] = self::$backup[$service];
            unset(self::$backup[$service]);
            return $overriddenService;

        }

        if ($shared && !empty(self::$services[$service])) {
            return self::$services[$service];
        }

        try {
            $class = $this->getFactory($service)->createService($this);
        } catch (FactoryMayIncompatibleException $e) {
            $class = $this->getService($service);
        }

        self::$services[$service] = $class;

        return $class;
    }

    /**
     * Get specific service by class name
     *
     * @param  string $service
     * @return mixed
     * @throws ServiceNotFoundException
     */
    private function getService(string $service)
    {
        if (!class_exists($service)) {
            throw new ServiceNotFoundException($service . ' not found');
        }

        return new $service();
    }

    /**
     * Check if we have a factory for this service
     *
     * @param string $service
     * @return FactoryInterface|null
     * @throws FactoryMayIncompatibleException
     */
    private function getFactory(string $service)
    {
        $parts     = explode('\\', $service);
        $className = array_splice($parts, count($parts) - 1, 1);
        $class     = implode('\\', $parts) . '\\Factory\\' . $className[0] . 'Factory';

        $isAutoDetected = class_exists($class) && in_array(FactoryInterface::class, class_implements($class));
        $isDirectAccess = class_exists($service) && in_array(FactoryInterface::class, class_implements($service));

        if ($isAutoDetected) {
            return new $class();
        }

        // This is a direct factory access
        if ($isDirectAccess) {
            return new $service();
        }

        throw new FactoryMayIncompatibleException();
    }

    /**
     * @param string           $name
     * @param ServiceInterface $service
     * @internal
     */
    public function set($name, $service)
    {
        if (isset(self::$services[$name])) {
            self::$backup[$name] = self::$services[$name];
        }

        self::$services[$name] = $service;
    }

    /**
     * Reset the service locators instance
     *
     * @internal
     */
    public static function destroy()
    {
        self::$instance = null;
    }

}
API documentation generated by ApiGen