code: public function applyDefaults($config, array $defaults, $depth = 1)
      {
          if (!is_int($depth) || $depth < 0) {
              throw new \InvalidArgumentException("Depth must be non-negative integer.");
          }
          
          if (!is_array($config)) {
              return $defaults;
          }
          
          if ($depth === 0) {
              $config += $defaults;
              return $config;
          }
  
          foreach ($defaults as $key => $defaultValue) {
              // Use the default value, if user's array is missing this key
              if (!isset($config[$key])) {
                  $config[$key] = $defaultValue;
                  continue;
              }
  
              if (is_array($defaultValue)) {
                  if (is_array($config[$key])) {
                      $config[$key] = $this->applyDefaults($config[$key], $defaultValue, $depth-1);
                  } else {
                      throw new ConfigurationException("Configuration key "
                          .$key." expects an array, a scalar value found.");
                  }
              } else {
                  if (is_array($config[$key])) {
                      throw new ConfigurationException("Configuration key "
                          .$key." expects scalar, an array found.");
                  }
              }
          }
  
          return $config;
      }
docs: Returns configuration merged with the default values
  
  Performs a union operation up to {$depth} level of sub-arrays.
  
  @param array|null $config The configuration array supplied by the user
  @param array $defaults The default configuration array
  @return array The resulting configuration array