<commit_before><?php
/* ===========================================================================
 * Opis Project
 * http://opis.io
 * ===========================================================================
 * Copyright 2013-2015 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============================================================================ */

namespace Opis\Container;

use Closure;
use ReflectionClass;
use RuntimeException;
use InvalidArgumentException;
use Serializable;
use Opis\Closure\SerializableClosure;

/**
 * Container
 *
 * The serializable container class
 */

class Container implements Serializable
{
    /** @var	array	The container's bindings. */
    protected $bindings  = array();
    
    /** @var 	array 	The container's singleton instances. */
    protected $instances = array();
    
    /** @var 	array	Aliased types. */
    protected $aliases = array();
    
    /**
     * Builds an instance of a concrete class
     *
     * @access  protected
     *
     * @throws  \Opis\Container\BindingException    If the concrete type is not instantiable
     * 
     * @param   string|\Closure $concrete           The concrete class name or a closure callback
     * @param   array           $arguments          Arguments that will be passed to the constructor
     *
     * @return  mixed
     */
    
    protected function build($concrete, array $arguments = array())
    {
        if($concrete instanceof Closure)
        {
            return $concrete($this, $arguments);
        }
        
        $reflection = new ReflectionClass($concrete);
        
        if(!$reflection->isInstantiable())
        {
            throw new BindingException($concrete . ' is not instantiable');
        }
        
        $constructor = $reflection->getConstructor();
        
        if(is_null($constructor))
        {
            return new $concrete();
        }
        
        return $reflection->newInstanceArgs($this->resolveConstructor($constructor, $arguments));
        
    }
    
    /**
     * Resolves arguments that will be passed to the constructor of a concrete class
     *
     * @access  protected
     *
     * @throws  \Opis\Container\BindingException    If the arguments can't be resolved
     * 
     * @param   \ReflectionMethod   $constructor    Constructor info
     * @param	array               $arguments      Constructor's arguments
     *
     * @return  array   Resolved arguments
     */
    
    protected function resolveConstructor($constructor, array $arguments)
    {
        $parameters = array_diff_key($constructor->getParameters(), $arguments);
        
        foreach($parameters as $key => $parameter)
        {
            if(null === $class = $parameter->getClass())
            {
                if($parameter->isDefaultValueAvailable())
                {
                    $arguments[$key] = $parameter->getDefaultValue();
                }
                else
                {
                    throw new BindingException("Could not resolve [$parameter]");
                }
            }
            else
            {
                $class = $class->name;
                try
                {
                    $arguments[$key] = isset($this->bindings[$class]) ? $this->make($class) : $this->build($class);
                }
                catch(BindingException $e)
                {
                    if($parameter->isOptional())
                    {
                        $arguments[$key] = $parameter->getDefaultValue();
                    }
                    else
                    {
                        throw $e;
                    }
                }
            }
        }
        
        return $arguments;
    }
    
    /**
     * Resolves an abstract type to a concrete class
     *
     * @access  protected
     *
     * @throws  \RuntimeException   If circular reference is detected
     * <commit_msg>Bugfix<commit_after><?php
/* ===========================================================================
 * Opis Project
 * http://opis.io
 * ===========================================================================
 * Copyright 2013-2015 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============================================================================ */

namespace Opis\Container;

use Closure;
use ReflectionClass;
use RuntimeException;
use InvalidArgumentException;
use Serializable;
use Opis\Closure\SerializableClosure;

/**
 * Container
 *
 * The serializable container class
 */

class Container implements Serializable
{
    /** @var	array	The container's bindings. */
    protected $bindings  = array();
    
    /** @var 	array 	The container's singleton instances. */
    protected $instances = array();
    
    /** @var 	array	Aliased types. */
    protected $aliases = array();
    
    /**
     * Builds an instance of a concrete class
     *
     * @access  protected
     *
     * @throws  \Opis\Container\BindingException    If the concrete type is not instantiable
     * 
     * @param   string|\Closure $concrete           The concrete class name or a closure callback
     * @param   array           $arguments          Arguments that will be passed to the constructor
     *
     * @return  mixed
     */
    
    protected function build($concrete, array $arguments = array())
    {
        if($concrete instanceof Closure)
        {
            return $concrete($this, $arguments);
        }
        
        $reflection = new ReflectionClass($concrete);
        
        if(!$reflection->isInstantiable())
        {
            throw new BindingException($concrete . ' is not instantiable');
        }
        
        $constructor = $reflection->getConstructor();
        
        if(is_null($constructor))
        {
            return new $concrete();
        }
        
        return $reflection->newInstanceArgs($this->resolveConstructor($constructor, $arguments));
        
    }
    
    /**
     * Resolves arguments that will be passed to the constructor of a concrete class
     *
     * @access  protected
     *
     * @throws  \Opis\Container\BindingException    If the arguments can't be resolved
     * 
     * @param   \ReflectionMethod   $constructor    Constructor info
     * @param	array               $arguments      Constructor's arguments
     *
     * @return  array   Resolved arguments
     */
    
    protected function resolveConstructor($constructor, array $arguments)
    {
        $parameters = array_diff_key($constructor->getParameters(), $arguments);
        
        foreach($parameters as $key => $parameter)
        {
            if(null === $class = $parameter->getClass())
            {
                if($parameter->isDefaultValueAvailable())
                {
                    $arguments[$key] = $parameter->getDefaultValue();
                }
                else
                {
                    throw new BindingException("Could not resolve [$parameter]");
                }
            }
            else
            {
                $class = $class->name;
                try
                {
                    $arguments[$key] = isset($this->bindings[$class]) ? $this->make($class) : $this->build($class);
                }
                catch(BindingException $e)
                {
                    if($parameter->isOptional())
                    {
                        $arguments[$key] = $parameter->getDefaultValue();
                    }
                    else
                    {
                        throw $e;
                    }
                }
            }
        }
        
        ksort($arguments);
        
        return $arguments;
    }
    
    /**
     * Resolves an abstract type to a concrete class
     *
     * @access  protected
     *
     * @throws  \RuntimeException   If circular reference is detected
     * 
{'fraction_non_alphanumeric': 0.14066524806809272, 'fraction_numerical': 0.0026878709821928546, 'mean_word_length': 1.8232690483717988, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2529798', 'n_tokens_mistral': 2187, 'n_tokens_neox': 2061, 'n_words': 605}