def testConstructor(self):
        """
        @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag.__construct

        """

        parameters = {
            'foo': 'foo',
            'bar': 'bar',
        };
        bag = FrozenParameterBag(parameters);
        self.assertEqual(parameters, bag.all(), '__init__() takes an array of parameters as its first argument');
Beispiel #2
0
    def compile(self):
        """Compiles the container.

        This method does two things:

            Parameter values are resolved;
            The parameter bag is frozen.

        @api:

        """
        self._parameterBag.resolve()
        self._parameterBag = FrozenParameterBag(self._parameterBag.all())
    def testAdd(self):
        """
        @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag.add
        @expectedException LogicException

        """

        try:
            bag = FrozenParameterBag({})
            bag.add({})

            self.fail()
        except Exception as e:
            self.assertTrue(isinstance(e, LogicException))
    def testConstructor(self):
        """
        @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag.__construct

        """

        parameters = {
            'foo': 'foo',
            'bar': 'bar',
        }
        bag = FrozenParameterBag(parameters)
        self.assertEqual(
            parameters, bag.all(),
            '__init__() takes an array of parameters as its first argument')
    def testAdd(self):
        """
        @covers Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag.add
        @expectedException LogicException

        """

        try:
            bag = FrozenParameterBag({});
            bag.add({});

            self.fail()
        except Exception as e:
            self.assertTrue(isinstance(e, LogicException));
Beispiel #6
0
    def __init__(self, parameterBag=None):
        """Constructor.

        @param: ParameterBagInterface parameterBag A ParameterBagInterface instance

        @api

        """
        self._services = dict()
        self._scopes = dict()
        self._scopeChildren = dict()
        self._scopedServices = dict()
        self._scopeStacks = dict()
        self._parameterBag = None
        self._loading = dict()

        if parameterBag is None:
            self._parameterBag = ParameterBag()
        else:
            assert isinstance(parameterBag, ParameterBagInterface)
            self._parameterBag = parameterBag

        self.set('service_container', self)
Beispiel #7
0
class Container(IntrospectableContainerInterface):
    """Container is a dependency injection container.

    It gives access to object instances (services).

    Services and parameters are simple key/pair stores.

    Parameter and service keys are case insensitive.

    A service id can contain lowercased letters, digits, underscores, and dots.
    Underscores are used to separate words, and dots to group services
    under namespaces:

    <ul>
      <li>request</li>
      <li>mysql_session_storage</li>
      <li>symfony.mysql_session_storage</li>
    </ul>

    A service can also be defined by creating a method named
    getXXXService(), where XXX is the camelized version of the id:

    <ul>
      <li>request -> getRequestService()</li>
      <li>mysql_session_storage -> getMysqlSessionStorageService()</li>
      <li>symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()</li>
    </ul>

    The container can have three possible behaviors when a service does not exist:

    * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default)
    * None_ON_INVALID_REFERENCE:      Returns None
    * IGNORE_ON_INVALID_REFERENCE:    Ignores the wrapping command asking for the reference
                                      (for instance, ignore a setter if the service does not exist):

    @author: Fabien Potencier <*****@*****.**>
    @author: Johannes M. Schmitt <*****@*****.**>

    @api:

    """
    def __init__(self, parameterBag=None):
        """Constructor.

        @param: ParameterBagInterface parameterBag A ParameterBagInterface instance

        @api

        """
        self._services = dict()
        self._scopes = dict()
        self._scopeChildren = dict()
        self._scopedServices = dict()
        self._scopeStacks = dict()
        self._parameterBag = None
        self._loading = dict()

        if parameterBag is None:
            self._parameterBag = ParameterBag()
        else:
            assert isinstance(parameterBag, ParameterBagInterface)
            self._parameterBag = parameterBag

        self.set('service_container', self)

    def compile(self):
        """Compiles the container.

        This method does two things:

            Parameter values are resolved;
            The parameter bag is frozen.

        @api:

        """
        self._parameterBag.resolve()
        self._parameterBag = FrozenParameterBag(self._parameterBag.all())

    def isFrozen(self):
        """Returns True if the container parameter bag are frozen.:

        @return: Boolean True if the container parameter bag are frozen, False otherwise

        @api:

        """
        return isinstance(self._parameterBag, FrozenParameterBag)

    def getParameterBag(self):
        """Gets the service container parameter bag.

        @return: ParameterBagInterface A ParameterBagInterface instance

        @api

        """
        return self._parameterBag

    def getParameter(self, name):
        """Gets a parameter.

        @param: string name The parameter name

        @return mixed  The parameter value

        @raise InvalidArgumentException if the parameter is not defined:

        @api

        """
        return self._parameterBag.get(name)

    def hasParameter(self, name):
        """Checks if a parameter exists.:

        @param: string name The parameter name

        @return Boolean The presence of parameter in container

        @api

        """
        return self._parameterBag.has(name)

    def setParameter(self, name, value):
        """Sets a parameter.

        @param: string name  The parameter name
        @param mixed  value The parameter value

        @api

        """
        self._parameterBag.set(name, value)

    def set(self,
            identifier,
            service,
            scope=ContainerInterface.SCOPE_CONTAINER):
        """Sets a service.

        @param: string identifier  The service identifier:
        @param object service      The service instance
        @param string scope        The scope of the service

        @raise RuntimeException When trying to set a service in an inactive scope
        @raise InvalidArgumentException When trying to set a service in the prototype scope

        @api

        """
        if (self.SCOPE_PROTOTYPE == scope):
            raise InvalidArgumentException(
                'You cannot set service "{0}" of scope "prototype".'
                ''.format(identifier))

        identifier = self._formatIdentifier(identifier)

        if (self.SCOPE_CONTAINER != scope):
            if not scope in self._scopedServices:
                raise RuntimeException(
                    'You cannot set service "{0}" of inactive scope.'
                    ''.format(identifier))

            self._scopedServices[scope][identifier] = service

        self._services[identifier] = service

    def has(self, identifier):
        """Returns True if the given service is defined.:

        @param: string id The service identifier:

        @return Boolean True if the service is defined, False otherwise:

        @api

        """
        identifier = self._formatIdentifier(identifier)
        method = 'get' + self.camelize(identifier) + 'Service'
        return identifier in self._services.keys() or (
            hasattr(self, method)
            and isinstance(getattr(self, method), type(self.has)))

    def get(self,
            identifier,
            invalidBehavior=ContainerInterface.EXCEPTION_ON_INVALID_REFERENCE):
        """Gets a service.

        If a service is defined both through a set() method and
        with a getidService() method, the former has always precedence.

        @param: string  id              The service identifier:
        @param integer invalidBehavior The behavior when the service does not exist

        @return object The associated service

        @raise InvalidArgumentException if the service is not defined:
        @raise ServiceCircularReferenceException When a circular reference is detected
        @raise ServiceNotFoundException When the service is not defined

        @see Reference

        @api

        """
        identifier = self._formatIdentifier(identifier)
        if identifier in self._services.keys():
            return self._services[identifier]

        if identifier in self._loading.keys():
            raise ServiceCircularReferenceException(identifier,
                                                    list(self._loading.keys()))

        method = 'get' + self.camelize(identifier) + 'Service'
        if (hasattr(self, method)
                and isinstance(getattr(self, method), type(self.get))):
            self._loading[identifier] = True

            try:
                service = getattr(self, method)()
            except Exception as e:
                self._loading.pop(identifier, None)

                self._services.pop(identifier, None)

                raise e

            self._loading.pop(identifier, None)

            return service

        if (self.EXCEPTION_ON_INVALID_REFERENCE == invalidBehavior):
            raise ServiceNotFoundException(identifier)

    def initialized(self, identifier):
        """Returns True if the given service has actually been initialized:

        @param: string id The service identifier:

        @return Boolean True if service has already been initialized, False otherwise:

        """
        identifier = self._formatIdentifier(identifier)
        return identifier in self._services

    def getServiceIds(self):
        """Gets all service ids.

        @return: list An array of all defined service ids

        """

        ids = list()
        r = ReflectionObject(self)
        for method in r.getMethods():
            match = re.search('^get(.+)Service$', method.getName())
            if match:
                ids.append(self.underscore(match.group(1)))

        return Array.uniq(ids + list(self._services.keys()))

    def enterScope(self, name):
        """This is called when you enter a scope

        @param: string name

        @raise RuntimeException         When the parent scope is inactive
        @raise InvalidArgumentException When the scope does not exist

        @api

        """

        if name not in self._scopes:
            raise InvalidArgumentException(
                'The scope "{0}" does not exist.'.format(name))

        if self.SCOPE_CONTAINER != self._scopes[name] and self._scopes[
                name] not in self._scopedServices:
            raise RuntimeException(
                'The parent scope "{0}" must be active when entering this '
                'scope.'.format(self._scopes[name]))

        # check if a scope of this name is already active, if so we need to
        # remove all services of this scope, and those of any of its child
        # scopes from the global services map
        if name in self._scopedServices:
            services = OrderedDict()
            services[0] = self._services
            services[name] = self._scopedServices[name]
            self._scopedServices.pop(name, None)

            for child in self._scopeChildren[name]:
                if child in self._scopedServices:
                    services[child] = self._scopedServices[child]
                    self._scopedServices.pop(child, None)

            # update global map
            self._services = Array.diffKey(*services.values())
            services.pop(0)

            # add stack entry for this scope so we can restore the removed services later
            if name not in self._scopeStacks:
                self._scopeStacks[name] = list()

            self._scopeStacks[name].append(services)

        self._scopedServices[name] = dict()

    def leaveScope(self, name):
        """This is called to leave the current scope, and move back to the parent
        scope.

        @param: string name The name of the scope to leave

        @raise InvalidArgumentException if the scope is not active:

        @api

        """

        if name not in self._scopedServices:
            raise InvalidArgumentException(
                'The scope "{0}" is not active.'.format(name))

        # remove all services of this scope, or any of its child scopes from
        # the global service map
        services = [self._services, self._scopedServices[name]]
        self._scopedServices.pop(name, None)
        for child in self._scopeChildren[name]:
            if child not in self._scopedServices:
                continue

            services.append(self._scopedServices[child])
            self._scopedServices.pop(child, None)

        self._services = Array.diffKey(*services)

        # check if we need to restore services of a previous scope of this type:
        if name in self._scopeStacks and self._scopeStacks[name]:
            services = self._scopeStacks[name].pop()
            self._scopedServices.update(services)

            for scopeServices in services.values():
                self._services.update(scopeServices)

    def addScope(self, scope):
        """Adds a scope to the container.

        @param: ScopeInterface scope

        @raise InvalidArgumentException

        @api

        """
        assert isinstance(scope, ScopeInterface)

        name = scope.getName()
        parentScope = scope.getParentName()

        if (self.SCOPE_CONTAINER == name or self.SCOPE_PROTOTYPE == name):
            raise InvalidArgumentException(
                'The scope "{0}" is reserved.'.format(name))

        if name in self._scopes:
            raise InvalidArgumentException(
                'A scope with name "{0}" already exists.'.format(name))

        if self.SCOPE_CONTAINER != parentScope and parentScope not in self._scopes:
            raise InvalidArgumentException(
                'The parent scope "{0}" does not exist, or is invalid.'
                ''.format(parentScope))

        self._scopes[name] = parentScope
        self._scopeChildren[name] = list()

        # normalize the child relations
        while (parentScope != self.SCOPE_CONTAINER):
            self._scopeChildren[parentScope].append(name)
            parentScope = self._scopes[parentScope]

    def hasScope(self, name):
        """Returns whether this container has a certain scope

        @param: string name The name of the scope

        @return Boolean

        @api

        """

        return name in self._scopes

    def isScopeActive(self, name):
        """Returns whether this scope is currently active

        This does not actually check if the passed scope actually exists.:

        @param: string name

        @return Boolean

        @api

        """

        return name in self._scopedServices

    @classmethod
    def camelize(self, identifier):
        """Camelizes a string.

        @param: string identifier A string to camelize

        @return string The camelized string

        """
        def callback(match):
            if '.' == match.group(1):
                return '_' + str(match.group(2)).upper()
            else:
                return '' + str(match.group(2)).upper()

        return re.sub('(^|_|\.)+(.)', callback, identifier)

    @classmethod
    def underscore(cls, identifier):
        """A string to underscore.

        @param identifier: string The string to underscore

        @return: string The underscored string
        """
        value = str(identifier)
        # value = value.replace("_", ".");
        patterns = [
            r"([A-Z]+)([A-Z][a-z])",
            r"([a-z\d])([A-Z])",
        ]
        repls = [
            '\\1_\\2',
            '\\1_\\2',
        ]

        for i in range(len(patterns)):
            value = re.sub(patterns[i], repls[i], value)

        return value.lower()

    def _formatIdentifier(self, identifier):
        return str(identifier).lower()