text:
<?php

/*
 * This file is part of the symfony framework.
 *
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

/**
 * sfServiceDefinition represents a service definition.
 *
 * @package    symfony
 * @subpackage dependency_injection
 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
 * @version    SVN: $Id: sfServiceDefinition.php 269 2009-03-26 20:39:16Z fabien $
 */
class sfServiceDefinition
{
  protected
    $class        = null,
    $file         = null,
    $constructor  = null,
    $shared       = true,
    $arguments    = array(),
    $calls        = array(),
    $configurator = null;

  /**
   * Constructor.
   *
   * @param string $class     The service class
   * @param array  $arguments An array of arguments to pass to the service constructor
   */
  public function __construct($class, array $arguments = array())
  {
    $this->class     = $class;
    $this->arguments = $arguments;
  }

  /**
   * Sets the constructor method.
   *
   * @param  string              $method The method name
   *
   * @return sfServiceDefinition The current instance
   */
  public function setConstructor($method)
  {
    $this->constructor = $method;

    return $this;
  }

  /**
   * Gets the constructor method.
   *
   * @return sfServiceDefinition The constructor method name
   */
  public function getConstructor()
  {
    return $this->constructor;
  }

  /**
   * Sets the service class.
   *
   * @param  string              $class The service class
   *
   * @return sfServiceDefinition The current instance
   */
  public function setClass($class)
  {
    $this->class = $class;

    return $this;
  }

  /**
   * Sets the constructor method.
   *
   * @return string The service class
   */
  public function getClass()
  {
    return $this->class;
  }

  /**
   * Sets the constructor arguments to pass to the service constructor.
   *
   * @param  array               $arguments An array of arguments
   *
   * @return sfServiceDefinition The current instance
   */
  public function setArguments(array $arguments)
  {
    $this->arguments = $arguments;

    return $this;
  }

  /**
   * Adds a constructor argument to pass to the service constructor.
   *
   * @param  mixed               $argument An argument
   *
   * @return sfServiceDefinition The current instance
   */
  public function addArgument($argument)
  {
    $this->arguments[] = $argument;

    return $this;
  }

  /**
   * Gets the constructor arguments to pass to the service constructor.
   *
   * @return array The array of arguments
   */
  public function getArguments()
  {
    return $this->arguments;
  }

  /**
   * Sets the methods to call after service initialization.
   *
   * @param  array               $calls An array of method calls
   *
   * @return sfServiceDefinition The current instance
   */
  public function setMethodCalls(array $calls = array())
  {
    $this->calls = array();
    foreach ($calls as $call)
    {
      $this->addMethodCall($call[0], $call[1]);
    }

    return $this;
  }

  /**
   * Adds a method to call after service initialization.
   *
   * @param  string              $method    The method name to call
   * @param  array               $arguments An array of arguments to pass to the method call
   *
   * @return sfServiceDefinition The current instance
   */
  public function addMethodCall($method, array $arguments = array())
  {
    $this->calls[] = array($method, $arguments);

    return $this;
  }

  /**
   * Gets the methods to call after service initialization.
   *
   * @return  array An array of method calls
   */
  public function getMethodCalls()
  {
    return $this->calls;
  }

  /**
   * Sets a file to require before creating the service.
   *
   * @param  string              $file A full pathname to include
   *
   * @return sfServiceDefinition The current instance
   */
  public function setFile($file)
  {
    $this->file = $file;

    return $this;
  }

  /**
   * Gets the file to require before creating the service.
   *
   * @return string The full pathname to include
   */
  public function getFile()
  {
    return $this->file;
  }

  /**
   * Sets if the service must be shared or not.
   *
   * @param  Boolean             $shared Whether the service must be shared or not
   *
   * @return sfServiceDefinition The current instance
   */
  public function setShared($shared)
  {
    $this->shared = (Boolean) $shared;

    return $this;
  }

  /**
   * Returns true if the service must be shared.
   *
   * @return Boolean true if the service is shared, false otherwise
   */
  public function isShared()
  {
    return $this->shared;
  }

  /**
   * Sets a configurator to call after the service is fully initialized.
   *
   * @param  mixed               $callable A PHP callable
   *
   * @return sfServiceDefinition The current instance
   */
  public function setConfigurator($callable)
  {
    $this->configurator = $callable;

    return $this;
  }

  /**
   * Gets the configurator to call after the service is fully initialized.
   *
   * @return mixed The PHP callable to call
   */
  public function getConfigurator()
  {
    return $this->configurator;
  }
}


text:
<?php

/*
 * This file is part of the symfony framework.
 *
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * This source file is subject to the MIT license that is bundled
 * with this source code in the file LICENSE.
 */

/**
 * sfServiceContainerLoaderFileIni loads parameters from INI files.
 *
 * @package    symfony
 * @subpackage dependency_injection
 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
 * @version    SVN: $Id$
 */
class sfServiceContainerLoaderFileIni extends sfServiceContainerLoaderFile
{
  public function doLoad($files)
  {
    $parameters = array();
    foreach ($files as $file)
    {
      $path = $this->getAbsolutePath($file);
      if (!file_exists($path))
      {
        throw new InvalidArgumentException(sprintf('The %s file does not exist.', $file));
      }

      $result = parse_ini_file($path, true);
      if (false === $result || array() === $result)
      {
        throw new InvalidArgumentException(sprintf('The %s file is not valid.', $file));
      }

      if (isset($result['parameters']) && is_array($result['parameters']))
      {
        foreach ($result['parameters'] as $key => $value)
        {
          $parameters[strtolower($key)] = $value;
        }
      }
    }

    return array(array(), $parameters);
  }
}

repo_name: michael-romer/zf-boilerplate

repo_language: PHP

mime_type: text/html


text:
<?php

namespace Bisna\Application\Container;

use Bisna\Application\Exception,
    Doctrine\DBAL\Types\Type,
    Doctrine\Common\Annotations\AnnotationRegistry;

/**
 * Doctrine Container class.
 *
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 */
class DoctrineContainer
{
    /**
     * @var string Default DBAL Connection name.
     */
    public $defaultConnection = 'default';

    /**
     * @var default Default Cache Instance name.
     */
    public $defaultCacheInstance = 'default';

    /**
     * @var string Default ORM EntityManager name.
     */
    public $defaultEntityManager = 'default';

    /**
     * @var array Doctrine Context configuration.
     */
    private $configuration = array();

    /**
     * @var array Available DBAL Connections.
     */
    private $connections = array();

    /**
     * @var array Available Cache Instances.
     */
    private $cacheInstances = array();

    /**
     * @var array Available ORM EntityManagers.
     */
    private $entityManagers = array();

    /**
     * Constructor.
     *
     * @param array $config Doctrine Container configuration
     */
    public function __construct(array $config = array())
    {
        // Registering Class Loaders
        if (isset($config['classLoader'])) {
            $this->registerClassLoaders($config['classLoader']);
        }

        // Defining DBAL configuration
        $dbalConfig = $this->prepareDBALConfiguration($config);

        // Defining default DBAL Connection name
        $this->defaultConnection = $dbalConfig['defaultConnection'];

        // Defining Cache configuration
        $cacheConfig = array();

        if (isset($config['cache'])) {
            $cacheConfig = $this->prepareCacheInstanceConfiguration($config);

            // Defining default Cache instance
            $this->defaultCacheInstance = $cacheConfig['defaultCacheInstance'];
        }

        // Defining ORM configuration
        $ormConfig = array();

        if (isset($config['orm'])) {
            $ormConfig  = $this->prepareORMConfiguration($config);

            // Defining default ORM EntityManager
            $this->defaultEntityManager = $ormConfig['defaultEntityManager'];
        }

        // Defining Doctrine Context configuration
        $this->configuration = array(
            'dbal'  => $dbalConfig['connections'],
            'cache' => $cacheConfig['instances'],
            'orm'   => $ormConfig['entityManagers']
        );
    }

    /**
     * Register Doctrine Class Loaders
     *
     * @param array Doctrine Class Loader configuration
     */
    private function registerClassLoaders(array $config = array())
    {
        $classLoaderClass = $config['loaderClass'];
        $classLoaderFile  = $config['loaderFile'];

        require_once $classLoaderFile;

        foreach ($config['loaders'] as $loaderItem) {
            $classLoader = new $classLoaderClass($loaderItem['namespace'], $loaderItem['includePath']);
            $classLoader->register();
        }
    }

    /**
     * Prepare DBAL Connections configurations.
     *
     * @param array $config Doctrine Container configuration
     *
     * @return array
     */
    private function prepareDBALConfiguration(array $config = array())
    {
        $dbalConfig = $config['dbal'];
        $defaultConnectionName = isset($dbalConfig['defaultConnection'])
            ? $dbalConfig['defaultConnection'] : $this->defaultConnection;

        unset($dbalConfig['defaultConnection']);

        $defaultConnection = array(
            'eventManagerClass'  => 'Doctrine\Common\EventManager',
            'eventSubscribers'   => array(),
            'configurationClass' => 'Doctrine\DBAL\Configuration',
            'sqlLoggerClass'     => null,
            'types'              => array(),
            'parameters'         => array(
                'wrapperClass'       => null,
                'driver'              => 'pdo_mysql',
                'host'                => 'localhost',
                'user'                => 'root',
                'password'            => null,
                'port'                => null,
                'driverOptions'       => array()
            )
        );

        $connections = array();

        if (isset($dbalConfig['connections'])) {
            $configConnections = $dbalConfig['connections'];

            foreach ($configConnections as $name => $connection) {
                $name = isset($connection['id']) ? $connection['id'] : $name;
                $connections[$name] = array_replace_recursive($defaultConnection, $connection);
            }
        } else {
            $connections = array(
                $defaultConnectionName => array_replace_recursive($defaultConnection, $dbalConfig)
            );
        }

        return array(
            'defaultConnection' => $defaultConnectionName,
            'connections'       => $connections
        );
    }

    /**
     * Prepare Cache Instances configurations.
     *
     * @param array $config Doctrine Container configuration
     *
     * @return array
     */
    private function prepareCacheInstanceConfiguration(array $config = array())
    {
        $cacheConfig = $config['cache'];
        $defaultCacheInstanceName = isset($cacheConfig['defaultCacheInstance'])
            ? $cacheConfig['defaultCacheInstance'] : $this->defaultCacheInstance;

        unset($cacheConfig['defaultCacheInstance']);

        $defaultCacheInstance = array(
            'adapterClass' => 'Doctrine\Common\Cache\ArrayCache',
            'namespace'    => '',
            'options'      => array()
        );

        $instances = array();

        if (isset($cacheConfig['instances'])) {
            $configInstances = $cacheConfig['instances'];

            foreach ($configInstances as $name => $instance) {
                $name = isset($instance['id']) ? $instance['id'] : $name;
                $instances[$name] = array_replace_recursive($defaultCacheInstance, $instance);
            }
        } else {
            $instances = array(
                $defaultCacheInstanceName => array_replace_recursive($defaultCacheInstance, $cacheConfig)
            );
        }

        return array(
            'defaultCacheInstance' => $defaultCacheInstanceName,
            'instances'            => $instances
        );
    }

    /**
     * Prepare ORM EntityManagers configurations.
     *
     * @param array $config Doctrine Container configuration
     *
     * @return array
     */
    private function prepareORMConfiguration(array $config = array())
    {
        $ormConfig = $config['orm'];
        $defaultEntityManagerName = isset($ormConfig['defaultEntityManager'])
            ? $ormConfig['defaultEntityManager'] : $this->defaultEntityManager;

        unset($ormConfig['defaultEntityManager']);

        $defaultEntityManager = array(
            'entityManagerClass'      => 'Doctrine\ORM\EntityManager',
            'configurationClass'      => 'Doctrine\ORM\Configuration',
            'entityNamespaces'        => array(),
            'connection'              => $this->defaultConnection,
            'proxy'                   => array(
                'autoGenerateClasses' => true,
                'namespace'           => 'Proxy',
                'dir'                 => APPLICATION_PATH . '/../library/Proxy'
            ),
            'queryCache'              => $this->defaultCacheInstance,
            'resultCache'             => $this->defaultCacheInstance,
            'metadataCache'           => $this->defaultCacheInstance,
            'metadataDrivers'         => array(),
            'DQLFunctions'            => array(
                'numeric'             => array(),
                'datetime'            => array(),
                'string'              => array()
            )
        );

        $entityManagers = array();

        if (isset($ormConfig['entityManagers'])) {
            $configEntityManagers = $ormConfig['entityManagers'];

            foreach ($configEntityManagers as $name => $entityManager) {
                $name = isset($entityManager['id']) ? $entityManager['id'] : $name;
                $entityManagers[$name] = array_replace_recursive($defaultEntityManager, $entityManager);
            }
        } else {
            $entityManagers = array(
                $this->defaultConnection => array_replace_recursive($defaultEntityManager, $ormConfig)
            );
        }

        return array(
            'defaultEntityManager' => $defaultEntityManagerName,
            'entityManagers'       => $entityManagers
        );
    }

    /**
     * Retrieve DBAL Connection based on its name. If no argument is provided,
     * it will attempt to get the default Connection.
     * If DBAL Connection name could not be found, NameNotFoundException is thrown.
     *
     * @throws Bisna\Application\Exception\NameNotFoundException
     *
     * @param string $connName Optional DBAL Connection name
     *
     * @return Doctrine\DBAL\Connection DBAL Connection
     */
    public function getConnection($connName = null)
    {
        $connName = $connName ?: $this->defaultConnection;

        // Check if DBAL Connection has not yet been initialized
        if ( ! isset($this->connections[$connName])) {
            // Check if DBAL Connection is configured
            if ( ! isset($this->configuration['dbal'][$connName])) {
                throw new Exception\NameNotFoundException("Unable to find Doctrine DBAL Connection '{$connName}'.");
            }

            $this->connections[$connName] = $this->startDBALConnection($this->configuration['dbal'][$connName]);

            unset($this->configuration['dbal'][$connName]);
        }

        return $this->connections[$connName];
    }

    /**
     * Retrieve Cache Instance based on its name. If no argument is provided,
     * it will attempt to get the default Instance.
     * If Cache Instance name could not be found, NameNotFoundException is thrown.
     *
     * @throws Bisna\Application\Exception\NameNotFoundException
     *
     * @param string $cacheName Optional Cache Instance name
     *
     * @return Doctrine\Common\Cache\Cache Cache Instance
     */
    public function getCacheInstance($cacheName = null)
    {
        $cacheName = $cacheName ?: $this->defaultCacheInstance;

        // Check if Cache Instance has not yet been initialized
        if ( ! isset($this->cacheInstances[$cacheName])) {
            // Check if Cache Instance is configured
            if ( ! isset($this->configuration['cache'][$cacheName])) {
                throw new Exception\NameNotFoundException("Unable to find Doctrine Cache Instance '{$cacheName}'.");
            }

            $this->cacheInstances[$cacheName] = $this->startCacheInstance($this->configuration['cache'][$cacheName]);

            unset($this->configuration['cache'][$cacheName]);
        }

        return $this->cacheInstances[$cacheName];
    }

    /**
     * Retrieve ORM EntityManager based on its name. If no argument provided,
     * it will attempt to get the default EntityManager.
     * If ORM EntityManager name could not be found, NameNotFoundException is thrown.
     *
     * @throws Bisna\Application\Exception\NameNotFoundException
     *
     * @param string $emName Optional ORM EntityManager name
     *
     * @return Doctrine\ORM\EntityManager ORM EntityManager
     */
    public function getEntityManager($emName = null)
    {
        $emName = $emName ?: $this->defaultEntityManager;

        // Check if ORM Entity Manager has not yet been initialized
        if ( ! isset($this->entityManagers[$emName])) {
            // Check if ORM EntityManager is configured
            if ( ! isset($this->configuration['orm'][$emName])) {
                throw new Exception\NameNotFoundException("Unable to find Doctrine ORM EntityManager '{$emName}'.");
            }

            $this->entityManagers[$emName] = $this->startORMEntityManager($this->configuration['orm'][$emName]);

            unset($this->configuration['orm'][$emName]);
        }

        return $this->entityManagers[$emName];
    }

    /**
     * Retrieves a list of names for all Entity Managers configured
     * and/or loaded
     *
     * @return array
     */
    public function getEntityManagerNames()
    {
       $configuredEMs = array_keys($this->configuration['orm']);
       $loadedEMs = array_keys($this->entityManagers);

       return array_merge($configuredEMs, $loadedEMs);
    }

    /**
     * Initialize the DBAL Connection.
     *
     * @param array $config DBAL Connection configuration.
     *
     * @return Doctrine\DBAL\Connection
     */
    private function startDBALConnection(array $config = array())
    {
        return \Doctrine\DBAL\DriverManager::getConnection(
            $config['parameters'],
            $this->startDBALConfiguration($config),
            $this->startDBALEventManager($config)
        );
    }

    /**
     * Initialize the DBAL Configuration.
     *
     * @param array $config DBAL Connection configuration.
     *
     * @return Doctrine\DBAL\Configuration
     */
    private function startDBALConfiguration(array $config = array())
    {
        $configClass = $config['configurationClass'];
        $configuration = new $configClass();

        // SQL Logger configuration
        if ( ! empty($config['sqlLoggerClass'])) {
            $sqlLoggerClass = $config['sqlLoggerClass'];
            $configuration->setSQLLogger(new $sqlLoggerClass());
        }

        //DBAL Types configuration
        $types = $config['types'];

        foreach ($types as $name => $className) {
            Type::addType($name, $className);
        }

        return $configuration;
    }

    /**
     * Initialize the EventManager.
     *
     * @param array $config DBAL Connection configuration.
     *
     * @return Doctrine\Common\EventManager
     */
    private function startDBALEventManager(array $config = array())
    {
        $eventManagerClass = $config['eventManagerClass'];
        $eventManager = new $eventManagerClass();

        // Event Subscribers configuration
        foreach ($config['eventSubscribers'] as $subscriber) {
       	    if ($subscriber) {
       	        $eventManager->addEventSubscriber(new $subscriber());
       	    }
        }

        return $eventManager;
    }

    /**
     * Initialize Cache Instance.
     *
     * @param array $config Cache Instance configuration.
     *
     * @return Doctrine\Common\Cache\Cache
     */
    private function startCacheInstance(array $config = array())
    {
        $adapterClass = $config['adapterClass'];
        $adapter = new $adapterClass();

        // Define namespace for cache
        if (isset($config['namespace']) && ! empty($config['namespace'])) {
            $adapter->setNamespace($config['namespace']);
        }

        if (method_exists($adapter, 'initialize')) {
            $adapter->initialize($config);
        } else if ($adapter instanceof \Doctrine\Common\Cache\MemcacheCache) {
            // Prevent stupid PHP error of missing extension (if other driver is being used)
            $memcacheClassName = 'Memcache';
            $memcache = new $memcacheClassName();

            // Default server configuration
            $defaultServer = array(
                'host'          => 'localhost',
                'port'          => 11211,
                'persistent'    => true,
                'weight'        => 1,
                'timeout'       => 1,
                'retryInterval' => 15,
                'status'        => true
            );

            if (isset($config['options']['servers'])) {
                foreach ($config['options']['servers'] as $server) {
                    $server = array_replace_recursive($defaultServer, $server);

                    $memcache->addServer(
                        $server['host'],
                        $server['port'],
                        $server['persistent'],
                        $server['weight'],
                        $server['timeout'],
                        $server['retryInterval'],
                        $server['status']
                    );
                }
            }

            $adapter->setMemcache($memcache);
        }

        return $adapter;
    }

    /**
     * Initialize ORM EntityManager.
     *
     * @param array $config ORM EntityManager configuration.
     *
     * @return Doctrine\ORM\EntityManager
     */
    private function startORMEntityManager(array $config = array())
    {
        if (isset($config['entityManagerClass'])) {
            $entityManagerClass = $config['entityManagerClass'];
        } else {
            $entityManagerClass = '\Doctrine\ORM\EntityManager';
        }
        return $entityManagerClass::create(
            $this->getConnection($config['connection']),
            $this->startORMConfiguration($config)
        );
    }

    /**
     * Initialize ORM Configuration.
     *
     * @param array $config ORM EntityManager configuration.
     *
     * @return Doctrine\ORM\Configuration
     */
    private function startORMConfiguration(array $config = array())
    {
        $configClass = $config['configurationClass'];
        $configuration = new $configClass();

        $configuration = new \Doctrine\ORM\Configuration();

        // Entity Namespaces configuration
        foreach ($config['entityNamespaces'] as $alias => $namespace) {
            $configuration->addEntityNamespace($alias, $namespace);
        }

        // Proxy configuration
        $configuration->setAutoGenerateProxyClasses(
            ! in_array($config['proxy']['autoGenerateClasses'], array("0", "false", false))
        );
        $configuration->setProxyNamespace($config['proxy']['namespace']);
        $configuration->setProxyDir($config['proxy']['dir']);

        // Cache configuration
        $configuration->setMetadataCacheImpl($this->getCacheInstance($config['metadataCache']));
        $configuration->setResultCacheImpl($this->getCacheInstance($config['resultCache']));
        $configuration->setQueryCacheImpl($this->getCacheInstance($config['queryCache']));

        // Metadata configuration
        $configuration->setMetadataDriverImpl($this->startORMMetadata($config['metadataDrivers']));

        // DQL Functions configuration
        $dqlFunctions = $config['DQLFunctions'];

        foreach ($dqlFunctions['datetime'] as $name => $className) {
            $configuration->addCustomDatetimeFunction($name, $className);
        }

        foreach ($dqlFunctions['numeric'] as $name => $className) {
            $configuration->addCustomNumericFunction($name, $className);
        }

        foreach ($dqlFunctions['string'] as $name => $className) {
            $configuration->addCustomStringFunction($name, $className);
        }

        return $configuration;
    }

    /**
     * Initialize ORM Metadata drivers.
     *
     * @param array $config ORM Mapping drivers.
     *
     * @return Doctrine\ORM\Mapping\Driver\DriverChain
     */
    private function startORMMetadata(array $config = array())
    {
        $metadataDriver = new \Doctrine\ORM\Mapping\Driver\DriverChain();

        // Default metadata driver configuration
        $defaultMetadataDriver = array(
            'adapterClass'               => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver',
            'mappingNamespace'           => '',
            'mappingDirs'                => array(),
            'annotationReaderClass'      => 'Doctrine\Common\Annotations\AnnotationReader',
            'annotationReaderCache'      => $this->defaultCacheInstance,
            'annotationReaderNamespaces' => array()
        );

        // Setup AnnotationRegistry
        if (isset($config['annotationRegistry'])) {
            $this->startAnnotationRegistry($config['annotationRegistry']);
        }

        foreach ($config['drivers'] as $driver) {
            $driver = array_replace_recursive($defaultMetadataDriver, $driver);

            $reflClass = new \ReflectionClass($driver['adapterClass']);
            $nestedDriver = null;

            if (
                $reflClass->getName() == 'Doctrine\ORM\Mapping\Driver\AnnotationDriver' ||
                $reflClass->isSubclassOf('Doctrine\ORM\Mapping\Driver\AnnotationDriver')
            ) {
                $annotationReaderClass = $driver['annotationReaderClass'];
                $annotationReader = new $annotationReaderClass();

                if (method_exists($annotationReader, 'setDefaultAnnotationNamespace')) {
                    $annotationReader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
                }

                if (method_exists($annotationReader, 'setAnnotationNamespaceAlias')) {
                    $driver['annotationReaderNamespaces']['ORM'] = 'Doctrine\ORM\Mapping\\';

                    foreach ($driver['annotationReaderNamespaces'] as $alias => $namespace) {
                        $annotationReader->setAnnotationNamespaceAlias($namespace, $alias);
                    }
                }

                $indexedReader = new \Doctrine\Common\Annotations\CachedReader(
                    new \Doctrine\Common\Annotations\IndexedReader($annotationReader),
                    $this->getCacheInstance($driver['annotationReaderCache'])
                );

                $nestedDriver = $reflClass->newInstance($indexedReader, $driver['mappingDirs']);
            } else {
                $nestedDriver = $reflClass->newInstance($driver['mappingDirs']);
            }

            $metadataDriver->addDriver($nestedDriver, $driver['mappingNamespace']);
        }

        if (($drivers = $metadataDriver->getDrivers()) && count($drivers) == 1) {
            reset($drivers);
            $metadataDriver = $drivers[key($drivers)];
        }

        return $metadataDriver;
    }

    /**
     * Initialize ORM Metatada Annotation Registry driver
     *
     * @param array $config  ORM Annotation Registry configuration.
     */
    private function startAnnotationRegistry($config)
    {
        // Load annotations from Files
        if (isset($config['annotationFiles']) && is_array($config['annotationFiles'])) {
            foreach($config['annotationFiles'] as $file) {
                AnnotationRegistry::registerFile($file);
            }
        }

        // Load annotation namespaces
        if (isset($config['annotationNamespaces']) && is_array($config['annotationNamespaces'])) {
            foreach($config['annotationNamespaces'] as $annotationNamespace) {
                AnnotationRegistry::registerAutoloadNamespace(
                        $annotationNamespace['namespace'],
                        $annotationNamespace['includePath']
                );
            }

        }
    }
}


text:
<?php

namespace Bisna\Application\Exception;

/**
 * NameNotFoundException class.
 *
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 */
class NameNotFoundException extends \Exception
{
}


text:
<?php

/**
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the LGPL. For more information, see
 * <http://www.doctrine-project.org>.
 */

// Zend Framework cannot deal with Resources using namespaces
//namespace Bisna\Application\Resource;

use Bisna\Application\Container;

/**
 * Zend Application Resource Doctrine class
 *
 * @license http://www.opensource.org/licenses/lgpl-license.php LGPL
 * @link www.doctrine-project.org
 *
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 */
class Bisna_Application_Resource_Doctrine extends \Zend_Application_Resource_ResourceAbstract
{
    /**
     * Initializes Doctrine Context.
     *
     * @return Core\Application\Container\DoctrineContainer
     */
    public function init()
    {
        $config = $this->getOptions();

        // Bootstrapping Doctrine autoloaders
        $this->registerAutoloaders($config);

        // Starting Doctrine container
        $container = new Container\DoctrineContainer($config);

        // Add to Zend Registry
        \Zend_Registry::set('doctrine', $container);
        \Zend_Registry::set('em', $container->getEntityManager());
        \Zend_Registry::set('cache', $container->getCacheInstance());
        return $container;
    }

    /**
     * Register Doctrine autoloaders
     *
     * @param array Doctrine global configuration
     */
    private function registerAutoloaders(array $config = array())
    {
        $autoloader = \Zend_Loader_Autoloader::getInstance();
        $doctrineIncludePath = isset($config['includePath'])
            ? $config['includePath'] : APPLICATION_PATH . '/../library/Doctrine';

        require_once $doctrineIncludePath . '/Common/ClassLoader.php';

        $symfonyAutoloader = new \Doctrine\Common\ClassLoader('Symfony');
        $autoloader->pushAutoloader(array($symfonyAutoloader, 'loadClass'), 'Symfony');

        $doctrineExtensionsAutoloader = new \Doctrine\Common\ClassLoader('DoctrineExtensions');
        $autoloader->pushAutoloader(array($doctrineExtensionsAutoloader, 'loadClass'), 'DoctrineExtensions');

        $doctrineAutoloader = new \Doctrine\Common\ClassLoader('Doctrine');
        $autoloader->pushAutoloader(array($doctrineAutoloader, 'loadClass'), 'Doctrine');
    }
}


text:
<?php

/**
 * Elastica searchable interface
 *
 * @category Xodoa
 * @package Elastica
 * @author Thibault Duplessis <thibault.duplessis@gmail.com>
 */
interface Elastica_Searchable
{
	/**
	 * Searches results for a query
	 *
	 * TODO: Improve sample code
	 * {
	 *	 "from" : 0,
	 *	 "size" : 10,
	 *	 "sort" : {
	 *		  "postDate" : {"reverse" : true},
	 *		  "user" : { },
	 *		  "_score" : { }
	 *	  },
	 *	  "query" : {
	 *		  "term" : { "user" : "kimchy" }
	 *	  }
	 * }
	 *
	 * @param string|array|Elastica_Query $query Array with all query data inside or a Elastica_Query object
	 * @return Elastica_ResultSet ResultSet with all results inside
	 */
	public function search($query);

	/**
	 * Counts results for a query
	 *
	 * @param string|array|Elastica_Query $query Array with all query data inside or a Elastica_Query object
	 * @return int number of documents matching the query
	 */
	public function count($query);
}


text:
<?php
/**
 * Elastica cluster node object
 *
 * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-status.html
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Node
{
	protected $_name = '';

	protected $_stats = null;

	protected $_info = null;

	/**
	 * Create a new node object
	 *
	 * @param string $name Node name
	 * @param Elastica_Client $client Node object
	 */
	public function __construct($name, Elastica_Client $client) {
		$this->_name = $name;
		$this->_client = $client;
		$this->refresh();
	}

	public function getName() {
		return $this->_name;
	}

	/**
	 * Returns the current client object
	 *
	 * @return Elastica_Client Client
	 */
	public function getClient() {
		return $this->_client;
	}

	/**
	 * Return stats object of the current node
	 *
	 * @return Elastica_Node_Stats Node stats
	 */
	public function getStats() {
		if (!$this->_stats) {
			$this->_stats = new Elastica_Node_Stats($this);
		}

		return $this->_stats;
	}

	public function getInfo() {
		if (!$this->_info) {
			$this->_info = new Elastica_Node_Info($this);
		}

		return $this->_info;
	}

	public function refresh() {
		$this->_stats = null;
		$this->_info = null;
	}
}


text:
<?php
/**
 * Elastica Request object
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Request {

	const POST = 'POST';
	const PUT = 'PUT';
	const GET = 'GET';
	const DELETE = 'DELETE';

	protected $_path;
	// TODO: set default method?
	protected $_method;
	protected $_data;

	/**
	 * @param string $path Request path
	 * @param string $method Request method (use const's)
	 * @param array $data Data array
	 */
	public function __construct($path, $method, $data = array()) {
		$this->_path = $path;
		$this->_method = $method;
		$this->_data = $data;
	}

	/**
	 * Sets the request method. Use one of the for consts
	 *
	 * @param string $method Request method
	 * @return Elastica_Request Current object
	 */
	public function setMethod($method) {
		$this->_method = $method;
		return $this;
	}

	/**
	 * @return string Request method
	 */
	public function getMethod() {
		return $this->_method;
	}

	/**
	 * Sets the request data
	 *
	 * @param array $data Request data
	 */
	public function setData($data) {
		$this->_data = $data;
		return $this;
	}

	/**
	 * @return array Request data
	 */
	public function getData() {
		return $this->_data;
	}

	/**
	 * Sets the request path
	 *
	 * @param string $path Request path
	 * @return Elastica_Request Current object
	 */
	public function setPath($path) {
		$this->_path = $path;
		return $this;
	}

	/**
	 * @return string Request path
	 */
	public function getPath() {
		return $this->_path;
	}
}


text:
<?php
/**
 * Elastica general status
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-status.html
 */
class Elastica_Status
{

	/**
	 * Contains all status infos
	 *
	 * @var Elastica_Response Response object
	 */
	protected $_response = null;

	protected $_data = array();

	protected $_client = null;

	/**
	 * Constructs Status object
	 *
	 * @param Elastica_Client $client Client object
	 */
	public function __construct(Elastica_Client $client) {
		$this->_client = $client;
		$this->refresh();
	}

	/**
	 * Returns status data
	 *
	 * @return array Status data
	 */
	public function getData() {
		return $this->_data;
	}

	/**
	 * Returns status objects of all indices
	 *
	 * @return array List of Elastica_Client_Index objects
	 */
	public function getIndexStatuses() {
		$statuses = array();
		foreach ($this->getIndexNames() as $name) {
			$index = new Elastica_Index($this->_client, $name);
			$statuses[] = new Elastica_Index_Status($index);
		}
		return $statuses;
	}

	/**
	 * Returns a list of the existing index names
	 *
	 * @return array Index names list
	 */
	public function getIndexNames() {
		$names = array();
		foreach($this->_data['indices'] as $name => $data) {
			$names[] = $name;
		}
		return $names;
	}

	/**
	 * Checks if the given index exists
	 *
	 * @param string $name Index name to check
	 * @return bool True if index exists
	 */
	public function indexExists($name) {
		return in_array($name, $this->getIndexNames());
	}

	/**
	 * Checks if the given alias exists
	 *
	 * @param string $name Alias name
	 * @return bool True if alias exists
	 */
	public function aliasExists($name) {
		foreach ($this->getIndexStatuses() as $status) {
			if ($status->hasAlias($name)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Returns an array with all indices that the given alias name points to
	 *
	 * @param string $name Alias name
	 * @return array List of Elastica_Index
	 */
	public function getIndicesWithAlias($name) {
		$indices = array();
		foreach ($this->getIndexStatuses() as $status) {
			if ($status->hasAlias($name)) {
				$indices[] = $status->getIndex();
			}
		}
		return $indices;
	}

	/**
	 * Returns response object
	 *
	 * @return Elastica_Response Response object
	 */
	public function getResponse() {
		return $this->_response;
	}

	/**
	 * @return array Shards info
	 */
	public function getShards() {
		return $this->_data['shards'];
	}

	/**
	 * Refresh status object
	 */
	public function refresh() {
		$path = '_status';
		$this->_response = $this->_client->request($path, Elastica_Request::GET);
		$this->_data = $this->getResponse()->getData();
	}
}


text:
<?php
/**
 * Client to connect the the elasticsearch server
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Admin
{
}


text:
<?php
/**
 * Client to connect the the elasticsearch server
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Client
{
	/**
	 * Default elastic search port
	 */
	const DEFAULT_PORT = 9200;

	/**
	 * Default host
	 */
	const DEFAULT_HOST = 'localhost';

	/**
	 * Number of seconds after a timeout occurs for every request
	 * If using indexing of file large value necessary.
	 */
	const TIMEOUT = 300;

	/**
	 * Client host
	 *
	 * @var string Host
	 */
	protected $_host = self::DEFAULT_HOST;

	/**
	 * Client port
	 *
	 * @var int Port
	 */
	protected $_port = self::DEFAULT_PORT;

	/**
	 * HTTP Headers
	 */
	protected $_headers = array();

	/**
	 * Creates a new Elastica client
	 *
	 * @param string $host OPTIONAL Server host (default = self::DEFAULT_HOST)
	 * @param int $port OPTIONAL Port to connect (default = self::DEFAULT_PORT)
	 */
	public function __construct($host = self::DEFAULT_HOST, $port = self::DEFAULT_PORT) {
		$this->_host = $host;
		$this->_port = $port;
	}

	/**
	 * Returns the index for the given connection
	 *
	 * @param string $name Index name to create connection to
	 * @return Elastica_Index Index for the given name
	 */
	public function getIndex($name) {
		return new Elastica_Index($this, $name);
	}

	/**
	 * Returns host the client connects to
	 *
	 * @return string Host
	 */
	public function getHost() {
		return $this->_host;
	}

	/**
	 * Returns connection port of this client
	 *
	 * @return int Connection port
	 */
	public function getPort() {
		return intval($this->_port);
	}

	/**
	 * Adds a HTTP Header
	 *
	 * @param string $header The HTTP Header
	 * @param string $headerValue The HTTP Header Value
	 * @throws Elastica_Exception_Invalid If $header or $headerValue is not a string
	 */
	public function addHeader($header, $headerValue) {
		if (is_string($header) && is_string($headerValue)) {
			$this->_headers[$header] = $headerValue;
		} else {
			throw new Elastica_Exception_Invalid('Header must be a string');
		}
	}

	/**
	 * Remove a HTTP Header
	 *
	 * @param string $header The HTTP Header to remove
	 * @throws Elastica_Exception_Invalid IF $header is not a string
	 */
	public function removeHeader($header) {
		if (is_string($header)) {
			if (array_key_exists($header, $this->_headers)) {
				unset($this->_headers[$header]);
			}
		} else {
			throw new Elastica_Exception_Invalid('Header must be a string');
		}
	}

	/**
	 * Uses _bulk to send documents to the server
	 *
	 * Array of Elastica_Document as input. Index and type has to be
	 * set inside the document, because for bulk settings documents,
	 * documents can belong to any type and index
	 *
	 * @param array $docs Array of Elastica_Document
	 * @return Elastica_Response Response object
	 * @throws Elastica_Exception_Invalid If docs is empty
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/bulk/
	 */
	public function addDocuments(array $docs) {

		if (empty($docs)) {
			throw new Elastica_Exception_Invalid('Array has to consist of at least one element');
		}
		$params = array();

		foreach($docs as $doc) {
			$action = array(
				'index' => array(
					'_index' => $doc->getIndex(),
					'_type' => $doc->getType(),
					'_id' => $doc->getId()
				)
			);

			if($doc->getVersion() > 0) {
				$action['index']['_version'] = $doc->getVersion();
			}

			$params[] = $action;
			$params[] = $doc->getData();
		}
		return $this->bulk($params);
	}

	/**
	 * Bulk deletes documents (not implemented yet)
	 *
	 * @param array $docs Docs
	 * @throws Elastica_Exception
	 */
	public function deleteDocuments(array $docs) {
		// TODO: similar to delete ids but with type and index inside files
		throw new Elastica_Exception('not implemented yet');
	}

	/**
	 * Returns the status object for all indices
	 *
	 * @return Elastica_Status Status object
	 */
	public function getStatus() {
		return new Elastica_Status($this);
	}

	/**
	 * Returns the current cluster
	 *
	 * @return Elastica_Cluster Cluster object
	 */
	public function getCluster() {
		return new Elastica_Cluster($this);
	}

	/**
	 * Deletes documents with the given ids, index, type from the index
	 *
	 * @param array $ids Document ids
	 * @param string $index Index name
	 * @param string $type Type of documents
	 * @return Elastica_Response Response object
	 * @throws Elastica_Exception If ids is empty
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/bulk/
	 */
	public function deleteIds(array $ids, $index, $type) {
		if (empty($ids)) {
			throw new Elastica_Exception('Array has to consist of at least one id');
		}

		$params = array();
		foreach($ids as $id) {
			$action = array(
				'delete' => array(
					'_index' => $index,
					'_type' => $type,
					'_id' => $id,
				)
			);

			$params[] = $action;
		}

		return $this->bulk($params);
	}

	/**
	 * Bulk operation
	 *
	 * Every entry in the params array has to exactly on array
	 * of the bulk operation. An example param array would be:
	 *
	 * array(
	 * 		array('index' => array('_index' => 'test', '_type' => 'user', '_id' => '1')),
	 * 		array('user' => array('name' => 'hans')),
	 * 		array('delete' => array('_index' => 'test', '_type' => 'user', '_id' => '2'))
	 * );
	 *
	 * @param array $params Parameter array
	 * @return Elastica_Response Reponse object
	 * @todo Test
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/bulk/
	 */
	public function bulk(array $params) {
		if (empty($params)) {
			throw new Elastica_Exception('Array has to consist of at least one param');
		}

		$path = '_bulk';

		$queryString = '';
		foreach($params as $index => $baseArray) {
			// Always newline needed
			$queryString .= json_encode($baseArray) . PHP_EOL;
		}

		$response = $this->request($path, Elastica_Request::PUT, $queryString);
		$data = $response->getData();

		foreach($data['items'] as $item) {
			$params = reset($item);
			if(isset($params['error'])) {
				throw new Elastica_Exception_BulkResponse($response);
			}
		}

		return $response;
	}

	/**
	 * Makes calls to the elasticsearch server based on this index
	 *
	 * It's possible to make any REST query directly over this method
	 *
	 * @param string $path Path to call
	 * @param string $method Rest method to use (GET, POST, DELETE, PUT)
	 * @param array $data OPTIONAL Arguments as array
	 * @return Elastica_Response Response object
	 */
	public function request($path, $method, $data = array()) {
		$request = new Elastica_Request($path, $method, $data);
		return $this->_callService($request);
	}

	/**
	 * Optimizes all search indices
	 *
	 * @param array $args OPTIONAL Optional arguments
	 * @return Elastica_Response Response object
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/optimize/
	 */
	public function optimizeAll($args = array()) {
		return $this->request('_optimize', Elastica_Request::POST, $args);
	}

	/**
	 * Makes calls to the elasticsearch server
	 *
	 * All calls that are made to the server are down over this function
	 *
	 * @param Elastica_Request $request Request object
	 * @return Elastica_Response Response object
	 */
	protected function _callService(Elastica_Request $request) {
		$conn = curl_init();
		$baseUri = 'http://' . $this->getHost() . ':' . $this->getPort() . '/';

		$baseUri .= $request->getPath();

		curl_setopt($conn, CURLOPT_URL, $baseUri);
		curl_setopt($conn, CURLOPT_TIMEOUT, self::TIMEOUT);
		curl_setopt($conn, CURLOPT_PORT, $this->getPort());
		curl_setopt($conn, CURLOPT_RETURNTRANSFER, 1) ;
		curl_setopt($conn, CURLOPT_CUSTOMREQUEST, $request->getMethod());

		if (!empty($this->_headers)) {
			$headers = array();
			while (list($header, $headerValue) = each($this->_headers)) {
				array_push($headers, $header . ': ' . $headerValue);
			}

			curl_setopt($conn, CURLOPT_HTTPHEADER, $headers);
		}

		// TODO: REFACTOR
		$data = $request->getData();

		if (!empty($data)) {
			if (is_array($data)) {
				$content = json_encode($data);
			} else {
				$content = $data;
			}

			// Escaping of / not necessary. Causes problems in base64 encoding of files
			$content = str_replace('\/', '/', $content);
			curl_setopt($conn, CURLOPT_POSTFIELDS, $content);
		}

		$start = microtime(true);
		$response = curl_exec($conn);
		$end = microtime(true);

		// Checks if error exists
		$errorNumber = curl_errno($conn);

		$response = new Elastica_Response($response);

		if (defined('DEBUG') && DEBUG) {
			$response->setQueryTime($end - $start);
			$response->setTransferInfo(curl_getinfo($conn));
		}

		if ($response->hasError()) {
			throw new Elastica_Exception_Response($response);
		}

		if ($errorNumber > 0) {
			throw new Elastica_Exception_Client($errorNumber, $request, $response);
		}

		return $response;
	}
}


text:
<?php
/**
 * Cluster informations for elasticsearch
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/cluster
 */
class Elastica_Cluster
{
	protected $_client = null;

	/**
	 * Creates a cluster object
	 *
	 * @param Elastica_Client $client Connection client object
	 */
	public function __construct(Elastica_Client $client) {
		$this->_client = $client;
		$this->refresh();
	}

	/**
	 * Refreshs all cluster information (state)
	 */
	public function refresh() {
		$path = '_cluster/state';
		$this->_response = $this->_client->request($path, Elastica_Request::GET);
		$this->_data = $this->getResponse()->getData();
	}

	/**
	 * Returns the response object
	 *
	 * @return Elastica_Response Response object
	 */
	public function getResponse() {
		return $this->_response;
	}

	/**
	 * Returns the full state of the cluster
	 *
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/cluster/state
	 * @return array State array
	 */
	public function getState() {
		return $this->_data;
	}

	/**
	 * Returns a list of existing node names
	 *
	 * @return array List of node names
	 */
	public function getNodeNames() {
		$data = $this->getState();
		return array_keys($data['routing_nodes']['nodes']);
	}

	/**
	 * Returns all nodes of the cluster
	 *
	 * @return array List of Elastica_Node objects
	 */
	public function getNodes() {
		$nodes = array();
		foreach ($this->getNodeNames() as $name) {
			$nodes[] = new Elastica_Node($name, $this->getClient());
		}
		return $nodes;
	}

	/**
	 * Returns the client object
	 *
	 * @return Elastica_Client Client object
	 */
	public function getClient() {
		return $this->_client;
	}

	/**
	 * Returns the cluster information (not implemented yet)
	 *
	 * @param array $args Additional arguemtns
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/cluster/nodes_info/
	 */
	public function getInfo(array $args) {
		throw new Exception('not implemented yet');
	}

	/**
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/cluster/health/
	 */
	public function getHealth($args = array()) {
		throw new Exception('not implemented yet');
	}

	/**
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/cluster/nodes_restart/
	 */
	public function restart(array $args) {
		throw new Exception('not implemented yet');

	}

	/**
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/cluster/nodes_shutdown/
	 */
	public function shutdown(array $args) {
		throw new Exception('not implemented yet');

	}
}


text:
<?php
/**
 * Elastica query object
 *
 * Creates different types of queries
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/search/
 */
class Elastica_Query
{
	protected $_query = array();

	/**
	 * Creates a query object
	 *
	 * @param array|Elastica_Query_Abstract $query OPTIONAL Query object (default = null)
	 */
	public function __construct($query = null) {
		if (is_array($query)) {
			$this->setRawQuery($query);
		} else if ($query instanceof Elastica_Query_Abstract) {
			$this->setQuery($query);
		}
	}

	/**
	 * Transforms a string or an array to a query object
	 *
	 * @param mixed $query
	 * @return Elastica_Query
	 **/
	public static function create($query) {
		switch (true) {
			case $query instanceof Elastica_Query:
				return $query;
			case $query instanceof Elastica_Query_Abstract:
				return new self($query);
			case is_string($query):
				return new self(new Elastica_Query_QueryString($query));
			case empty($query):
				return new self();
		}

		// TODO: Implement queries without
		throw new Elastica_Exception_NotImplemented();
	}

	/**
	 * Sets query as raw array. Will overwrite all already set arguments
	 *
	 * @param array $query Query array
	 * @return Elastica_Query Query object
	 */
	public function setRawQuery(array $query) {
		$this->_query = $query;
		return $this;
	}

	/**
	 * Sets a single param for the query
	 *
	 * @param string $key Key to set
	 * @param mixed $value Value
	 */
	public function setParam($key, $value) {
		$this->_query[$key] = $value;
		return $this;
	}

	/**
	 * Sets the query
	 *
	 * @param Elastica_Query_Abstract $query Query object
	 * @return Elastica_Query Query object
	 */
	public function setQuery(Elastica_Query_Abstract $query) {
		return $this->setParam('query', $query->toArray());
	}

	/**
	 * Gets the query array
	 *
	 * @return array
	 **/
	public function getQuery() {
		return $this->_query['query'];
	}

	/**
	 * @param Elastica_Filter_Abstract $filter Filter object
	 * @return Elastica_Query Current object
	 */
	public function setFilter(Elastica_Filter_Abstract $filter) {
		return $this->setParam('filter', $filter->toArray());
	}

	/**
	 * Sets the start from which the search results should be returned
	 *
	 * @param int $from
	 * @return Elastica_Query Query object
	 */
	public function setFrom($from) {
		return $this->setParam('from', $from);
	}

	/**
	 * Sets sort arguments for the query
	 * Replaces existing values
	 *
	 * @param array $sortArgs Sorting arguments
	 * @return Elastica_Query Query object
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/search/sort/
	 */
	public function setSort(array $sortArgs) {
		return $this->setParam('sort', $sortArgs);
	}

	/**
	 * Adds a sort param to the query
	 *
	 * @param mixed $sort Sort parameter
	 * @return Elastica_Query Query object
	 */
	public function addSort($sort) {
		// TODO: test
		$this->_query['sort'][] = $sort;
		return $this;
	}

	/**
	 * Sets highlight arguments for the query
	 *
	 * @param array $highlightArgs Set all highlight arguments
	 * @return Elastica_Query Query object
	 * @link http://www.elasticsearch.org/guide/reference/api/search/highlighting.html
	 */
	public function setHighlight(array $highlightArgs) {
		return $this->setParam('highlight', $highlightArgs);
	}

	/**
	 * Adds a highlight argument
	 *
	 * @param mixed $highlight Add highlight argument
	 * @return Elastica_Query Query object
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/search/highlighting/
	 */
	public function addHighlight($highlight) {
		$this->_query['highlight'][] = $highlight;
		return $this;
	}

	/**
	 * Alias for setLimit
	 *
	 * @param int $limit OPTIONAL Maximal number of results for query (default = 10)
	 * @return Elastica_Query Query object
	 */
	public function setSize($limit = 10) {
		return $this->setLimit($limit);
	}

	/**
	 * Sets maximum number of results for this query
	 *
	 * @param int $limit OPTIONAL Maximal number of results for query (default = 10)
	 * @return Elastica_Query Query object
	 */
	public function setLimit($limit = 10) {
		return $this->setParam('size', $limit);
	}

	/**
	 * Enables explain on the query
	 *
	 * @param bool $explain OPTIONAL Enabled or disable explain (default = true)
	 * @return Elastica_Query Current object
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/search/explain/
	 */
	public function setExplain($explain = true) {
		return $this->setParam('explain', $explain);
	}

	/**
	 * Enables version on the query
	 *
	 * @param bool $version OPTIONAL Enabled or disable version (default = true)
	 * @return Elastica_Query Current object
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/search/version/
	 */
	public function setVersion($version = true) {
		return $this->setParam('version', $version);
	}

	/**
	 * Sets the fields to be returned by the search
	 *
	 * @param array $fields Fields to be returne
	 * @return Elastica_Query Current object
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/search/fields/
	 */
	public function setFields(array $fields) {
		return $this->setParam('fields', $fields);
	}

	/**
	 * Set script fields
	 *
	 * @param array $scriptFields Script fields
	 * @return Elastica_Query Current object
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/search/script_fields/
	 */
	public function setScriptFields(array $scriptFields) {
		return $this->setParam('script_field', $scriptFields);
	}

	/**
	 * Sets all facets for this query object. Replaces existing facets
	 *
	 * @param array $facets List of facet objects
	 * @return Elastica_Query Query object
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/search/facets
	 */
	public function setFacets(array $facets) {
		$this->_query['facets'] = array();
		foreach ($facets as $facet) {
			$this->addFacet($facet);
		}
		return $this;
	}

	/**
	 * Adds a Facet to the query
	 *
	 * @param Elastica_Facet_Abstract $facet Facet object
	 * @return Elastica_Query Query object
	 */
	public function addFacet(Elastica_Facet_Abstract $facet) {
		$this->_query['facets'][$facet->getName()] = $facet->toArray();
		return $this;
	}

	/**
	 * Converts all query params to an array
	 *
	 * @return array Query array
	 */
	public function toArray() {

		// If no query is set, all query is chosen by default
		if (!isset($this->_query['query'])) {
			$this->setQuery(new Elastica_Query_MatchAll());
		}

		return $this->_query;
	}
}


text:
<?php
/**
 * Elastica type object
 *
 * elasticsearch has for every types as a substructure. This object
 * represents a type inside a context
 * The hirarchie is as following: client -> index -> type -> document
 *
 * Search over different indices and types is not supported yet {@link http://www.elasticsearch.com/docs/elasticsearch/rest_api/search/indices_types/}
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Type implements Elastica_Searchable
{
	/**
	 * @var Elastica_Index Index object
	 */
	protected $_index = null;

	/**
	 * @var string Object type
	 */
	protected $_type = '';

	/**
	 * Creates a new type object inside the given index
	 *
	 * @param Elastica_Index $index Index Object
	 * @param string $type Type name
	 */
	public function __construct(Elastica_Index $index, $type) {
		$this->_index = $index;
		$this->_type = $type;
	}

	/**
	 * Adds the given document to the search index
	 *
	 * @param Elastica_Document $doc Document with data
	 * @return Elastica_Response
	 */
	public function addDocument(Elastica_Document $doc) {
		$path = $doc->getId();
		if($doc->getVersion() > 0) {
			$path .= '?version=' . $doc->getVersion();
		}

		return $this->request($path, Elastica_Request::PUT, $doc->getData());
	}

	/**
	 * Uses _bulk to send documents to the server
	 *
	 * @param array $docs Array of Elastica_Document
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/bulk/
	 */
	public function addDocuments(array $docs) {

		foreach($docs as $doc) {
			$doc->setType($this->getType());
		}

		return $this->getIndex()->addDocuments($docs);
	}

	/**
	 * Get the document from search index
	 *
	 * @param string $id Document id
	 * @return Elastica_Document
	 */
	public function getDocument($id) {
		$path = $id;

		$result = $this->request($path, Elastica_Request::GET)->getData();

		$document = new Elastica_Document($id, $result['_source'], $this->getType(),  $this->getIndex());
		$document->setVersion($result['_version']);
		return $document;
	}

	/**
	 * Returns the type name
	 *
	 * @return string Type
	 */
	public function getType() {
		return $this->_type;
	}

	/**
	 * Sets value type mapping for this type
	 *
	 * @param array $properties Property array with all mappings
	 * @param bool $source OPTIONAL If source should be stored or not (default = true)
	 */
	public function setMapping(array $properties, $source = true) {
		$path = '_mapping';

		$data = array($this->getType() => array('properties' => $properties, '_source' => array('enabled' => $source)));

		return $this->request($path, Elastica_Request::PUT, $data);
	}

	/**
	 * Returns current mapping for the given type
	 *
	 * @return array Current mapping
	 */
	public function getMapping() {
		$path = '_mapping';

		$response = $this->request($path, Elastica_Request::GET);
		return $response->getData();
	}

	/**
	 * {@inheritDoc}
	 */
	public function search($query) {
		$query = Elastica_Query::create($query);
		$path = '_search';

		$response = $this->request($path, Elastica_Request::GET, $query->toArray());
		return new Elastica_ResultSet($response);
	}

	/**
	 * {@inheritDoc}
	 */
	public function count($query) {
		$query = Elastica_Query::create($query);
		$path = '_count';

		$data = $this->request($path, Elastica_Request::GET, $query->getQuery())->getData();
		return (int) $data['count'];
	}

	/**
	 * Returns index client
	 *
	 * @return Elastica_Index Index object
	 */
	public function getIndex() {
		return $this->_index;
	}

	/**
	 * Delete an entry by its unique identifier
	 *
	 * @param int|string $id Document id
	 * @link http://www.elasticsearch.org/guide/reference/api/delete.html
	 */
	public function deleteById($id) {
		if (empty($id) || !trim($id)) {
			throw new InvalidArgumentException();
		}
		$response = $this->request($id, Elastica_Request::DELETE);
	}

	/**
	 * Deletes entries in the db based on a query
	 *
	 * @param Elastica_Query $query Query object
	 * @link http://www.elasticsearch.org/guide/reference/api/delete-by-query.html
	 */
	public function deleteByQuery(Elastica_Query $query) {
		// TODO: To be implemented, can also be implemented on index and client level (see docs)
		throw new Elastica_Exception_NotImplemented();
	}

	/**
	 * More like this query based on the given object
	 *
	 * The id in the given object has to be set
	 *
	 * @param EalsticSearch_Document $doc Document to query for similar objects
	 * @param array $args OPTIONAL Additional arguments for the query
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/more_like_this/
	 */
	public function moreLikeThis(Elastica_Document $doc, $args = array()) {
		// TODO: Not tested yet
		$path = $doc->getId() . '/_mlt';
		return $this->request($path, Elastica_Request::GET, $args);
	}

	/**
	 * Makes calls to the elasticsearch server based on this type
	 *
	 * @param string $path Path to call
	 * @param string $method Rest method to use (GET, POST, DELETE, PUT)
	 * @param array $data OPTIONAL Arguments as array
	 * @return Elastica_Response Response object
	 */
	public function request($path, $method, $data = array()) {
		$path = $this->getType() . '/' . $path;
		return $this->getIndex()->request($path, $method, $data);
	}
}


text:
<?php
/**
 * Elastica result set
 *
 * List of all hits that are returned for a search on elasticsearch
 * Result set implents iterator
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_ResultSet implements Iterator
{
	protected $_results = array();
	protected $_position = 0;
	protected $_response = null;

	/**
	 * Constructs ResultSet object
	 *
	 * @param Elastica_Response $response Response object
	 */
	public function __construct(Elastica_Response $response) {
		$this->rewind();
		$this->_init($response);
	}

	/**
	 * Loads all data into the results object (initalisation)
	 *
	 * @param Elastica_Response $response Response object
	 */
	protected function _init(Elastica_Response $response) {
		$this->_response = $response;
		$result = $response->getData();
		$this->_totalHits = $result['hits']['total'];

		if (isset($result['hits']['hits'])) {
			foreach ($result['hits']['hits'] as $hit) {
				$this->_results[] = new Elastica_Result($hit);
			}
		}
	}

	/**
	 * Returns all results
	 *
	 * @return array Results
	 */
	public function getResults() {
		return $this->_results;
	}

	/**
	 * Returns all facets results
	 *
	 * @return array Facet results
	 */
	public function getFacets() {
		$data = $this->_response->getData();
		return $data['facets'];
	}

	/**
	 * Returns the total number of found hits
	 *
	 * @return int Total hits
	 */
	public function getTotalHits() {
		return (int) $this->_totalHits;
	}

	/**
	 * Returns response object
	 *
	 * @return Elastica_Response Response object
	 */
	public function getResponse() {
		return $this->_response;
	}

	/**
	 * Returns size of current set
	 *
	 * @return int Size of set
	 */
	public function count() {
		return sizeof($this->_results);
	}

	/**
	 * Returns the current object of the set
	 *
	 * @return mixed|bool Set object or false if not valid (no more entries)
	 */
	public function current() {
		if ($this->valid()) {
			return $this->_results[$this->key()];
		} else {
			return false;
		}
	}

	/**
	 * Sets pointer (current) to the next item of the set
	 */
	public function next() {
		$this->_position++;
		return $this->current();
	}

	/**
	 * Returns the position of the current entry
	 *
	 * @return int Current position
	 */
	public function key() {
		return $this->_position;
	}

	/**
	 * Check if an object exists at the current position
	 *
	 * @return bool True if object exists
	 */
	public function valid() {
		return isset($this->_results[$this->key()]);
	}

	/**
	 * Resets position to 0, restarts iterator
	 */
	public function rewind() {
		$this->_position = 0;
	}
}


text:
<?php
/**
 * Field in elastic search
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @todo Not implemented yet
 */
class Elastica_Field
{

	public function __construct($key, $value, $boost = 1) {
	}

	public function setBoost($boost) {
	}
}


text:
<?php
/**
 * Single document stored in elastic search
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Document {

	/**
	 * @var string|int	Document id
	 */
	protected $_id = '';

	/**
	 * @var array Document data
	 */
	protected $_data = array();

	protected $_type = '';
	protected $_index = '';

	protected $_version = '';

	/**
	 * Creates a new document
	 *
	 * @param int OPTIONAL $id Id is create if empty
	 * @param array $data OPTIONAL Data array
	 * @param string $type OPTIONAL Type name
	 * @param string $index OPTIONAL Index name
	 */
	public function __construct($id = '', array $data = array(), $type = '', $index = '') {
		$this->_id = $id;
		$this->setData($data);
		$this->setType($type);
		$this->setIndex($index);
	}

	/**
	 * Returns document id
	 *
	 * @return string|int Document id
	 */
	public function getId() {
		return $this->_id;
	}

	/**
	 * Adds the given key/value pair to the document
	 *
	 * @param string $key Document entry key
	 * @param mixed $value Document entry value
	 */
	public function add($key, $value) {
		$this->_data[$key] = $value;
	}

	/**
	 * Adds a file to the index
	 *
	 * To use this feature you have to call the following command in the
	 * elasticsearch directory:
	 * <code>
	 * ./bin/plugin install mapper-attachments
	 * </code>
	 * This installs the tika file analysis plugin. More infos about supported formats
	 * can be found here: {@link http://tika.apache.org/0.7/formats.html}
	 *
	 * @param string $key Key to add the file to
	 * @param string $filepath Path to add the file
	 * @param string $mimeType OPTIONAL Header mime type
	 */
	public function addFile($key, $filepath, $mimeType = '') {
		$value = base64_encode(file_get_contents($filepath));

		if (!empty($mimeType)) {
			$value = array(
				'_content_type' => $mimeType,
				'_name' => $filepath,
				'content' => $value,
			);
		}

		$this->add($key, $value);
	}

	/**
	 * Adds a geopoint to the document
	 *
	 * Geohashes re not yet supported
	 *
	 * @link http://www.elasticsearch.com/docs/elasticsearch/mapping/geo_point/
	 * @param string $key Field key
	 * @param float $latitude Latitud value
	 * @param float $longitude Longitude value
	 */
	public function addGeoPoint($key, $latitude, $longitude) {

		$value = array(
			'lat' => $latitude,
			'lon' => $longitude,
		);

		$this->add($key, $value);
	}

	/**
	 * Overwrites the curent document data with the given data
	 *
	 * @param array $data Data array
	 */
	public function setData(array $data) {
		$this->_data = $data;
	}

	/**
	 * Returns the document data
	 *
	 * @return array Document data
	 */
	public function getData() {
		return $this->_data;
	}

	public function setType($type) {
		$this->_type = $type;
	}

	public function getType() {
		$type = $this->_type;

		if (empty($type)) {
			throw new Elastica_Exception_Invalid('Type not set');
		}
		return $type;
	}

	public function setIndex($index) {
		$this->_index = $index;
	}

	public function getIndex() {
		$index = $this->_index;

		if (empty($index)) {
			throw new Elastica_Exception_Invalid('Index not set');
		}
		return $index;
	}

	/**
	 * Sets the version of a document for use with optimistic concurrency control
	 *
	 * @link http://www.elasticsearch.org/blog/2011/02/08/versioning.html
	 * @param int $version Document version
	 */
	public function setVersion($version) {
		if($version !== '') {
			$this->_version = (int) $version;
		}
	}

	/**
	 * Returns document version
	 *
	 * @return string|int Document version
	 */
	public function getVersion() {
		return $this->_version;
	}
}


text:
<?php
/**
 * Elastica result item
 *
 * Stores all information from a result
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Result
{
	protected $_hit;

	/**
	 * Constructs a single results object
	 *
	 * @param array $hit Hit data
	 */
	public function __construct(array $hit) {
		$this->_hit = $hit;
	}

	/**
	 * @return int Hit id
	 */
	public function getId() {
		return $this->_hit['_id'];
	}

	/**
	 * Returns results type
	 *
	 * @return string Result type
	 */
	public function getType() {
		return $this->_hit['_type'];
	}

	/**
	 * Returns the index name of the result
	 *
	 * @return string Index name
	 */
	public function getIndex() {
		return $this->_hit['_index'];
	}

	/**
	 * Returns the score of the result
	 *
	 * @return float Results score
	 */
	public function getScore() {
		return $this->_hit['_score'];
	}

	/**
	 * Returns the raw hit array
	 *
	 * @return array Hit array
	 */
	public function getHit() {
		return $this->_hit;
	}

	/**
	 * Returns the version information from the hit
	 *
	 * @return string|int Document version
	 */
	public function getVersion() {
		return $this->_hit['_version'];
	}

	/**
	 * Returns result data
	 *
	 * Alias for getSource
	 *
	 * @return array Result data array
	 */
	public function getData() {
		return $this->getSource();
	}

	/**
	 * Returns the result source
	 *
	 * @return array Source data array
	 */
	public function getSource() {
		if (isset($this->_hit['_source'])) {
			return $this->_hit['_source'];
		} else {
			return array();
		}
	}

	/**
	 * Returns result data
	 *
	 * @return array Result data array
	 */
	public function getHighlights() {
		if (isset($this->_hit['highlight'])) {
			return $this->_hit['highlight'];
		} else {
			return array();
		}
	}

	/**
	 * Returns explanation on how its score was computed.
	 *
	 * @return array explanations
	 */
	public function getExplanation() {
		if (isset($this->_hit['_explanation'])) {
			return $this->_hit['_explanation'];
		} else {
			return array();
		}
	}

	/**
	 * Magic function to directly access keys inside the result
	 *
	 * Returns null if key does not exist
	 *
	 * @param string $key Key name
	 * @return mixed Key value
	 */
	public function __get($key) {
		$source = $this->getData();
		return array_key_exists($key, $source) ? $source[$key] : null;
	}
}


text:
<?php
/**
 * Elastica Response object
 *
 * Stores query time, and result array -> is given to resultset, returned by ...
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Response {

	protected $_queryTime = null;
	protected $_responseString = '';
	protected $_error = false;
	protected $_transferInfo = array();

	/**
	 * @param string $responseString Response string (json)
	 */
	public function __construct($responseString) {
		$this->_responseString = $responseString;
	}

	/**
	 * @return string Error message
	 */
	public function getError() {
		$message = '';
		$response = $this->getData();

		if (isset($response['error'])) {
			$message = $response['error'];
		}
		return $message;
	}

	/**
	 * @return bool True if response has error
	 */
	public function hasError() {
		$response = $this->getData();

		if (isset($response['error'])) {
			return $response['error'];
		}
		return false;
	}

	/**
	 * @return array Response data array
	 */
	public function getData() {

		$response = $this->_responseString;
		if ($response === false) {
			$this->_error = true;
		} else {

			$tempResponse = json_decode($response, true);
			// If error is returned, json_decod makes empty string of string
			if (!empty($tempResponse)) {
				$response = $tempResponse;
			}
		}

		if (empty($response)) {
			$response = array();
		}

		if (is_string($response)) {
			$response = array('message' => $response);
		}

		return $response;
	}

	/**
	 * @return array Transfer info
	 */
	public function getTransferInfo() {
		return $this->_transferInfo;
	}

	/**
	 * Sets the transfer info
	 *
	 * @param array $transferInfo Transfer info
	 * @return Elastica_Response Current object
	 */
	public function setTransferInfo(array $transferInfo) {
		$this->_transferInfo = $transferInfo;
		return $this;
	}

	/**
	 * This is only available if DEBUG constant is set to true
	 *
	 * @return float Query time
	 */
	public function getQueryTime() {
		return $this->_queryTime;
	}

	/**
	 * Sets the query time
	 *
	 * @param float $queryTime Query time
	 * @return Elastica_Response Current object
	 */
	public function setQueryTime($queryTime) {
		$this->_queryTime = $queryTime;
		return $this;
	}
}


text:
<?php
/**
 * Elastica index object
 *
 * Handles reads, deletes and configurations of an index
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Index implements Elastica_Searchable
{
	/**
	 * @var string Index name
	 */
	protected $_name = '';

	/**
	 * @var Elastica_Client Client object
	 */
	protected $_client = null;

	/**
	 * Creates a new index object
	 *
	 * All the communication to and from an index goes of this object
	 *
	 * @param string $name Index name
	 */
	public function __construct(Elastica_Client $client, $name) {
		$this->_client = $client;

		if (!is_string($name)) {
			throw new Elastica_Exception_Invalid('Index name should be of type string');
		}
		$this->_name = $name;
	}

	/**
	 * Returns a type object for the current index with the given name
	 *
	 * @param string $type Type name
	 * @return Elastica_Type Type object
	 */
	public function getType($type) {
		return new Elastica_Type($this, $type);
	}

	/**
	 * Returns the current status of the index
	 *
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/status/
	 * @return array Index status
	 */
	public function getStatus() {
		return new Elastica_Index_Status($this);
	}

	/**
	 * Returns the index settings object
	 *
	 * @return Elastica_Index_Settings Settings object
	 */
	public function getSettings() {
		return new Elastica_Index_Settings($this);
	}

	/**
	 * Uses _bulk to send documents to the server
	 *
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/bulk/
	 * @param array $docs Array of Elastica_Document
	 */
	public function addDocuments(array $docs) {
		foreach ($docs as $doc) {
			$doc->setIndex($this->getName());
		}

		return $this->getClient()->addDocuments($docs);
	}

	/**
	 * Deletes the index
	 *
	 * @return Elastica_Response Response object
	 */
	public function delete() {
		$response = $this->request('', Elastica_Request::DELETE);

		return $response;
	}

	/**
	 * Optimizes search index
	 *
	 * Detailed arguments can be found here in the link
	 *
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/optimize/
	 * @param array $args OPTIONAL Additional arguments
	 * @return array Server response
	 */
	public function optimize($args = array()) {
		// TODO: doesn't seem to work?
		$this->request('_optimize', Elastica_Request::POST, $args);
	}

	/**
	 * Refreshs the index
	 *
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/refresh/
	 * @return Elastica_Response Response object
	 */
	public function refresh() {
		return $this->request('_refresh', Elastica_Request::POST, array());
	}

	/**
	 * Creates a new index with the given arguments
	 *
	 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/admin/indices/create_index/
	 * @param array $args OPTIONAL Arguments to use
	 * @param bool $recreate OPTIONAL Deletes index first if already exists (default = false)
	 * @return array Server response
	 */
	public function create(array $args = array(), $recreate = false) {
		if ($recreate) {
			try {
				$this->delete();
			} catch(Elastica_Exception_Response $e) {
				// Table can't be deleted, because doesn't exist
			}
		}
		return $this->request('', Elastica_Request::PUT, $args);
	}

	/**
	 * {@inheritDoc}
	 */
	public function search($query) {
		$query = Elastica_Query::create($query);
		$path = '_search';

		$response = $this->request($path, Elastica_Request::GET, $query->toArray());
		return new Elastica_ResultSet($response);
	}

	/**
	 * {@inheritDoc}
	 */
	public function count($query) {
		$query = Elastica_Query::create($query);
		$path = '_count';

		$data = $this->request($path, Elastica_Request::GET, $query->getQuery())->getData();
		return (int) $data['count'];
	}

	/**
	 * Opens an index
	 *
	 * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close.html
	 * @return Elastica_Response Response object
	 */
	public function open() {
		$this->request('_open', Elastica_Request::POST);
	}

	/**
	 * Closes the index
	 *
	 * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-open-close.html
	 * @return Elastica_Response Response object
	 */
	public function close() {
		return $this->request('_close', Elastica_Request::POST);
	}

	/**
	 * Returns the index name
	 *
	 * @return string Index name
	 */
	public function getName() {
		return $this->_name;
	}

	/**
	 * Returns index client
	 *
	 * @return Elastica_Client Index client object
	 */
	public function getClient() {
		return $this->_client;
	}

	/**
	 * Adds an alias to the current index
	 *
	 * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html
	 * @param string $name Alias name
	 * @param bool $replace OPTIONAL If set, an existing alias will be replaced
	 * @return Elastica_Response Response
	 */
	public function addAlias($name, $replace = false) {
		$path = '_aliases';

		if ($replace) {
			$status = new Elastica_Status($this->getClient());

			foreach ($status->getIndicesWithAlias($name) as $index) {
				$index->removeAlias($name);
			}
		}

		$data = array(
			'actions' => array(
				array(
					'add' => array(
						'index' => $this->getName(),
						'alias' => $name
					)
				)
			)
		);

		return $this->getClient()->request($path, Elastica_Request::POST, $data);
	}

	/**
	 * Removes an alias pointing to the current index
	 *
	 * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html
	 * @param string $name Alias name
	 * @return Elastica_Response Response
	 */
	public function removeAlias($name) {
		$path = '_aliases';

		$data = array(
			'actions' => array(
				array(
					'remove' => array(
						'index' => $this->getName(),
						'alias' => $name
					)
				)
			)
		);

		return $this->getClient()->request($path, Elastica_Request::POST, $data);
	}

	/**
	 * Can be used to change settings during runtime. One example is to use
	 * if for bulk updating {@link http://www.elasticsearch.org/blog/2011/03/23/update-settings.html}
	 *
	 * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-update-settings.html
	 * @param array $data Data array
	 * @return Elastica_Response Response object
	 */
	public function setSettings(array $data) {
		return $this->request('_settings', Elastica_Request::PUT, $data);
	}

	/**
	 * Makes calls to the elasticsearch server based on this index
	 *
	 * @param string $path Path to call
	 * @param string $method Rest method to use (GET, POST, DELETE, PUT)
	 * @param array $data OPTIONAL Arguments as array
	 * @return Elastica_Response Response object
	 */
	public function request($path, $method, $data = array()) {
		$path = $this->getName() . '/' . $path;
		return $this->getClient()->request($path, $method, $data);
	}
}


text:
<?php
/**
 * Bool query
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/query_dsl/bool_query/
 */
class Elastica_Query_Bool extends Elastica_Query_Abstract
{
	protected $_boost = 1.0;
	protected $_minimumNumberShouldMatch = 1;

	protected $_must = array();
	protected $_should = array();
	protected $_mustNot = array();

	/**
	 * Add should part to query
	 *
	 * @param Elastica_Query_Abstract|array $args Should query
	 * @return Elastica_Query_Bool Current object
	 */
	public function addShould($args) {
		return $this->_addQuery('should', $args);
	}

	/**
	 * Add must part to query
	 *
	 * @param Elastica_Query_Abstract|array $args Must query
	 * @return Elastica_Query_Bool Current object
	 */
	public function addMust($args) {
		return $this->_addQuery('must', $args);
	}

	/**
	 * Add must not part to query
	 *
	 * @param Elastica_Query_Abstract|array $args Must not query
	 * @return Elastica_Query_Bool Current object
	 */
	public function addMustNot($args) {
		return $this->_addQuery('mustNot', $args);
	}

	/**
	 * Adds a query to the current object
	 *
	 * @param string $type Query type
	 * @param Elastica_Query_Abstract|array $args Query
	 * @throws Elastica_Exception_Invalid If not valid query
	 */
	public function _addQuery($type, $args) {
		if ($args instanceof Elastica_Query_Abstract) {
			$args = $args->toArray();
		}

		if (!is_array($args)) {
			throw new Elastica_Exception_Invalid('Invalid parameter. Has to be array or instance of Elastica_Query');
		}

		$varName = '_' . $type;
		$this->{$varName}[] = $args;
		return $this;
	}

	/**
	 * Converts query to an array
	 *
	 * @return array Data array
	 * @see Elastica_Query_Abstract::toArray()
	 */
	public function toArray() {
		$args = array();

		if (!empty($this->_must)) {
			$args['must'] = $this->_must;
		}

		if (!empty($this->_should)) {
			$args['should'] = $this->_should;
			$args['minimum_number_should_match'] = $this->_minimumNumberShouldMatch;
		}

		if (!empty($this->_mustNot)) {
			$args['must_not'] = $this->_mustNot;
		}

		$args['boost'] = $this->_boost;

		return array('bool' => $args);
	}

	/**
	 * Sets boost value of this query
	 *
	 * @param float $boost Boost value
	 * @return Elastica_Query_Bool Current object
	 */
	public function setBoost($boost) {
		$this->_boost = $boost;
		return $this;
	}

	/**
	 * Set the minimum number of of should match
	 *
	 * @param int $minimumNumberShouldMatch Should match minimum
	 * @return Elastica_Query_Bool Current object
	 */
	public function setMinimumNumberShouldMatch($minimumNumberShouldMatch) {
		$this->_minimumNumberShouldMatch = (int) $minimumNumberShouldMatch;
		return $this;
	}

}


text:
<?php
/**
 * Filtered query. Needs a query and a filter
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/query_dsl/fuzzy_query/
 */
class Elastica_Query_Filtered extends Elastica_Query_Abstract
{
	protected $_query = null;
	protected $_filter = null;

	/**
	 * Constructs a filtered query
	 *
	 * @param Elastica_Query_Abstract $query Query object
	 * @param Elastica_Filter_Abstract $filter Filter object
	 */
	public function __construct(Elastica_Query_Abstract $query, Elastica_Filter_Abstract $filter) {
		$this->setQuery($query);
		$this->setFilter($filter);
	}

	/**
	 * Sets a query
	 *
	 * @param Elastica_Query_Abstract $query Query object
	 * @return Elastica_Query_Filtered Current object
	 */
	public function setQuery(Elastica_Query_Abstract $query) {
		$this->_query = $query;
		return $this;
	}

	/**
	 * Sets the filter
	 *
	 * @param Elastica_Filter_Abstract $filter Filter object
	 * @return Elastica_Query_Filtered Current object
	 */
	public function setFilter(Elastica_Filter_Abstract $filter) {
		$this->_filter = $filter;
		return $this;
	}

	/**
	 * Converts query to array
	 *
	 * @return array Query array
	 * @see Elastica_Query_Abstract::toArray()
	 */
	public function toArray() {
		return array('filtered' => array(
			'query' => $this->_query->toArray(),
			'filter' => $this->_filter->toArray()
		));
	}
}


text:
<?php
/**
 * Field query
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/query_dsl/field_query/
 */
class Elastica_Query_Field extends Elastica_Query_Abstract
{
	/**
	 * Converts query to array
	 *
	 * @return array Query array
	 * @see Elastica_Query_Abstract::toArray()
	 */
	public function toArray() {
		return array('field' => $args);
	}
}


text:
<?php
/**
 * Range query
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/query_dsl/range_query/
 */
class Elastica_Query_Range extends Elastica_Query_Abstract
{
	protected $_fields = array();

	/**
	 * Adds a range field to the query
	 *
	 * @param string $fieldName Field name
	 * @param array $args Field arguments
	 * @return Elastica_Query_Range Current object
	 */
	public function addField($fieldName, array $args) {
		$this->_fields[$fieldName] = $args;
		return $this;
	}

	/**
	 * Converst the range query to an array
	 *
	 * @return array Query array
	 * @see Elastica_Query_Abstract::toArray()
	 */
	public function toArray() {
		$args = $this->_fields;
		return array('range' => $args);
	}
}


text:
<?php
/**
 * Match all query. Returns all results
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Query_MatchAll extends Elastica_Query_Abstract
{
	/**
	 * Converts match all query to array
	 *
	 * @return array Query array
	 * @see Elastica_Query_Abstract::toArray()
	 */
	public function toArray() {
		return array('match_all' => new stdClass());
	}
}


text:
<?php
/**
 * Array query
 * Pure php array query. Can be used to create any not existing type of query.
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Query_Array extends Elastica_Query_Abstract
{
	protected $_query = array();

	/**
	 * Constructs a query based on an array
	 *
	 * @param array $query Query array
	 */
	public function __construct(array $query) {
		$this->setQuery($query);
	}

	/**
	 * Sets new query array
	 *
	 * @param array $query Query array
	 * @return Elastica_Query_Array Current object
	 */
	public function setQuery(array $query) {
		$this->_query = $query;
		return $this;
	}

	/**
	 * Converts query to array
	 *
	 * @return array Query array
	 * @see Elastica_Query_Abstract::toArray()
	 */
	public function toArray() {
		return $this->_query;
	}
}


text:
<?php
/**
 * Abstract query object. Should be extended by all query types.
 *
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
abstract class Elastica_Query_Abstract
{
	/**
	 * Converts a query to an array
	 *
	 * All query objects have to implement this function
	 *
	 * @return array Query array
	 */
	abstract public function toArray();
}


text:
<?php
/**
 * Wildcard query
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/query_dsl/wildcard_query
 */
class Elastica_Query_Wildcard extends Elastica_Query_Abstract
{
	protected $_key;
	protected $_value;
	protected $_boost;

	/**
	 * @param string $key Wildcard key
	 * @param string $value Wildcard value
	 * @param float $boost OPTIONAL Boost value (default = 1)
	 */
	public function __construct($key, $value, $boost = 1) {
		$this->_key = $key;
		$this->_value = $value;
		$this->_boost = $boost;
	}

	/**
	 * Returns query in form of an array
	 *
	 * @return array Query as array
	 */
	public function toArray() {
		return array('wildcard' => array(
			$this->_key => array(
				'value' => $this->_value,
				'boost' => $this->_boost)
			)
		);
	}
}


text:
<?php
/**
 * Term query
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/query_dsl/term_query/
 */
class Elastica_Query_Term extends Elastica_Query_Abstract
{
	protected $_term = array();

	/**
	 * Constructs the Term query object
	 *
	 * @param array $term OPTIONAL Calls setTerm with the given $term array
	 */
	public function __construct(array $term = array()) {
		$this->setTerm($term);
	}

	/**
	 * Set term can be used instead of addTerm if some more special
	 * values for a term have to be set.
	 *
	 * @param array $term Term array
	 * @return Elastica_Query_Term Current object
	 */
	public function setTerm(array $term) {
		$this->_term = $term;
		return $this;
	}

	/**
	 * Adds a term to the term query
	 *
	 * @param string $key Key to query
	 * @param string|array $value Values(s) for the query. Boost can be set with array
	 * @param float $boost OPTIONAL Boost value (default = 1.0)
	 * @return Elastica_Query_Term Current object
	 */
	public function addTerm($key, $value, $boost = 1.0) {
		// TODO: Why is return $this->setTerm(array($key => array('value' => $value, 'boost' => $boost)));
		// 		not working? Tested with filer
		return $this->setTerm(array($key => $value));
	}

	/**
	 * Converts the term query to an array
	 *
	 * @return array Array term query
	 */
	public function toArray() {
		$args = $this->_term;
		return array('term' => $args);
	}
}


text:
<?php
/**
 * Terms query
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.org/guide/reference/query-dsl/terms-query.html
 */
class Elastica_Query_Terms extends Elastica_Query_Abstract
{
	protected $_terms = array();
	protected $_params = array();
	protected $_key = '';

	/**
	 * @param string $key OPTIONAL Terms key
	 * @param array $terms OPTIONLA Terms list
	 */
	public function __construct($key = '', array $terms = array()) {
		$this->setTerms($key, $terms);
	}

	/**
	 * Sets key and terms for the query
	 *
	 * @param string $key Terms key
	 * @param array $terms Terms for the query.
	 */
	public function setTerms($key, array $terms) {
		$this->_key = $key;
		$this->_terms = array_values($terms);
		return $this;
	}

	/**
	 * Adds a single term to the list
	 *
	 * @param string $term Term
	 */
	public function addTerm($term) {
		$this->_terms[] = $term;
		return $this;
	}

	/**
	 * Sets a general parameter for the terms query array
	 *
	 * This can be used to set not supported params
	 *
	 * @param string $key Key to set
	 * @param mixed $value Value to key
	 */
	public function setParam($key, $value) {
		$this->_params[$key] = $value;
		return $this;
	}

	/**
	 * Sets the minimum matching values
	 *
	 * @param int $minimum Minimum value
	 */
	public function setMinimumMatch($minimum) {
		return $this->setParam('minimum_match', (int) $minimium);
	}

	/**
	 * Converts the terms object to an array
	 *
	 * @return array Query array
	 * @see Elastica_Query_Abstract::toArray()
	 */
	public function toArray() {
		if (empty($this->_key)) {
			throw new Elastica_Exception_Invalid('Terms key has to be set');
		}
		$this->_params[$this->_key] = $this->_terms;
		return array('terms' => $this->_params);
	}
}


text:
<?php
/**
 * QueryString query
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/query_dsl/query_string_query
 */
class Elastica_Query_QueryString extends Elastica_Query_Abstract
{
	protected $_queryString = '';
	protected $_defaultOperator = '';
	protected $_defaultField = '';

	/**
	 * Creates query string object. Calls setQuery with argument
	 *
	 * @param string $queryString OPTIONAL Query string for object
	 */
	public function __construct($queryString = '') {
		$this->setQueryString($queryString);
	}

	/**
	 * Sets a new query string for the object
	 *
	 * @param string $queryString Query string
	 * @return Elastica_Query_QueryString Current object
	 */
	public function setQueryString($queryString) {
		if (!is_string($queryString)) {
			throw new Elastica_Exception_Invalid('Parameter has to be a string');
		}

		$this->_queryString = $queryString;
		return $this;
	}

	/**
	 * Sets the default operator AND or OR
	 *
	 * If no operator is set, OR is chosen
	 *
	 * @param string $operator Operator
	 * @return Elastica_Query_QueryString Current object
	 */
	public function setDefaultOperator($operator) {
		$this->_defaultOperator = $operator;
		return $this;
	}

	/**
	 * Sets the default field
	 *
	 * If no field is set, _all is chosen
	 *
	 * @param string $field Field
	 * @return Elastica_Query_QueryString Current object
	 */
	public function setDefaultField($field) {
		$this->_defaultField = $field;
		return $this;
	}

	/**
	 * Converts the query string object to an array
	 *
	 * @return array Query string array
	 */
	public function toArray() {
		$args['query'] = $this->_queryString;

		if(!empty($this->_defaultOperator)) {
			$args['default_operator'] = $this->_defaultOperator;
		}

		if(!empty($this->_defaultField)) {
			$args['default_field'] = $this->_defaultField;
		}

		return array('query_string' => $args);
	}

	/**
	 * Escapes the following characters (because part of the query language)
	 * + - && || ! ( ) { } [ ] ^ " ~ * ? : \
	 *
	 * @param string $term Query term to escape
	 * @return string Escaped query term
	 * @link http://lucene.apache.org/java/2_4_0/queryparsersyntax.html#Escaping%20Special%20Characters
	 */
	public static function escapeTerm($term) {

		// \ escaping has to be first, otherwise escaped later once again
		$chars = array('\\', '+', '-', '&&', '||', '!', '(', ')', '{', '}', '[', ']', '^', '"', '~', '*', '?', ':');

		foreach ($chars as $char) {
			$term = str_replace($char, '\\' . $char, $term);
		}

		return $term;
	}
}


text:
<?php
/**
 * Fuzzy query
 *
 * @uses Elastica_Query_Abstract
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 * @link http://www.elasticsearch.com/docs/elasticsearch/rest_api/query_dsl/fuzzy_query/
 */
class Elastica_Query_Fuzzy extends Elastica_Query_Abstract
{
	protected $_fields = array();

	/**
	 * Adds field to fuzzy query
	 *
	 * @param string $fieldName Field name
	 * @param array $args Data array
	 * @return Elastica_Query_Fuzzy Current object
	 */
	public function addField($fieldName, array $args) {
		$this->_fields[$fieldName] = $args;
		return $this;
	}

	/**
	 * Converts fuzzy query to array
	 *
	 * @return array Query array
	 * @see Elastica_Query_Abstract::toArray()
	 */
	public function toArray() {
		$args = $this->_fields;
		return array('fuzzy' => $args);
	}
}


text:
<?php
/**
 * Elastica cluster node object
 *
 * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-status.html
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Node_Info
{
	protected $_response = null;

	protected $_data = array();

	protected $_node = null;

	public function __construct(Elastica_Node $node) {
		$this->_node = $node;
		$this->refresh();
	}

	/**
	 * Returns the entry in the data array based on the params.
	 * Various params possible.
	 *
	 * Example 1: get('os', 'mem', 'total') returns total memory of the system the
	 * node is running on
	 * Example 2: get('os', 'mem') returns an array with all mem infos
	 *
	 * @return mixed Data array entry or null if not found
	 */
	public function get() {

		$data = $this->getData();

		foreach (func_get_args() as $arg) {
			if (isset($data[$arg])) {
				$data = $data[$arg];
			} else {
				return null;
			}
		}

		return $data;
	}

	public function getData() {
		return $this->_data;
	}

	public function getName() {
		return $this->_name;
	}

	public function getNode() {
		return $this->_node;
	}

	/**
	 * Returns response object
	 *
	 * @return Elastica_Response Response object
	 */
	public function getResponse() {
		return $this->_response;
	}

	/**
	 * Reloads all nodes information. Has to be called if informations changed
	 *
	 * @return Elastica_Response Response object
	 */
	public function refresh() {
		$path = '_cluster/nodes/' . $this->getNode()->getName();
		$this->_response = $this->getNode()->getClient()->request($path, Elastica_Request::GET);
		$data = $this->getResponse()->getData();
		$this->_data = reset($data['nodes']);
	}
}


text:
<?php
/**
 * Elastica cluster node object
 *
 * @link http://www.elasticsearch.org/guide/reference/api/admin-indices-status.html
 * @category Xodoa
 * @package Elastica
 * @author Nicolas Ruflin <spam@ruflin.com>
 */
class Elastica_Node_Stats
{
	protected $_response = null;

	protected $_data = array();

	protected $_node = null;

	public function __construct(Elastica_Node $node) {
		$this->_node = $node;
		$this->refresh();
	}

	public function get() {

		$data = $this->getData();

		foreach (func_get_args() as $arg) {
			if (isset($data[$arg])) {
				$data = $data[$arg];
			} else {
				return null;
			}
		}

		return $data;
	}

	public function getData() {
		return $this->_data;
	}

	public function getNode() {
		return $this->_node;
	}

	/**
	 * Returns response object
	 *
	 * @return Elastica_Response Response object
	 */
	public function getResponse() {
		return $this->_response;
	}

	/**
	 * Reloads all nodes information. Has to be called if informations changed
	 *
	 * @return Elastica_Response Response object
	 */
	public function refresh() {
		$path = '_cluster/nodes/' . $this->getNode()->getName() . '/stats';
		$this->_response = $this->getNode()->getClient()->request($path, Elastica_Request::GET);
		$data = $this->getResponse()->getData();
		$this->_data = reset($data['nodes']);
	}
}