<?php

namespace Cdb\Writer;

use Cdb\Exception;
use Cdb\Util;
use Cdb\Writer;

/**
 * This is a port of D.J. Bernstein's CDB to PHP. It's based on the copy that
 * appears in PHP 5.3. Changes are:
 *    * Error returns replaced with exceptions
 *    * Exception thrown if sizes or offsets are between 2GB and 4GB
 *    * Some variables renamed
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 */

/**
 * CDB writer class
 */
class PHP extends Writer {
	protected $hplist;

	protected $numentries;

	protected $pos;

	/**
	 * @param string $fileName
	 */
	public function __construct( $fileName ) {
		$this->realFileName = $fileName;
		$this->tmpFileName = $fileName . '.tmp.' . mt_rand( 0, 0x7fffffff );
		$this->handle = fopen( $this->tmpFileName, 'wb' );
		if ( !$this->handle ) {
			$this->throwException(
				'Unable to open CDB file "' . $this->tmpFileName . '" for write.' );
		}
		$this->hplist = [];
		$this->numentries = 0;
		$this->pos = 2048; // leaving space for the pointer array, 256 * 8
		if ( fseek( $this->handle, $this->pos ) == -1 ) {
			$this->throwException( 'fseek failed in file "' . $this->tmpFileName . '".' );
		}
	}

	/**
	 * @param string $key
	 * @param string $value
	 */
	public function set( $key, $value ) {
		if ( strval( $key ) === '' ) {
			// DBA cross-check hack
			return;
		}
		$this->addbegin( strlen( $key ), strlen( $value ) );
		$this->write( $key );
		$this->write( $value );
		$this->addend( strlen( $key ), strlen( $value ), Util::hash( $key ) );
	}

	/**
	 * @throws Exception
	 */
	public function close() {
		$this->finish();
		if ( isset( $this->handle ) ) {
			fclose( $this->handle );
		}
		if ( $this->isWindows() && file_exists( $this->realFileName ) ) {
			unlink( $this->realFileName );
		}
		if ( !rename( $this->tmpFileName, $this->realFileName ) ) {
			$this->throwException( 'Unable to move the new CDB file into place.' );
		}
		unset( $this->handle );
	}

	/**
	 * @throws Exception
	 * @param string $buf
	 */
	protected function write( $buf ) {
		$len = fwrite( $this->handle, $buf );
		if ( $len !== strlen( $buf ) ) {
			$this->throwException( 'Error writing to CDB file "' . $this->tmpFileName . '".' );
		}
	}

	/**
	 * @throws Exception
	 * @param int $len
	 */
	protected function posplus( $len ) {
		$newpos = $this->pos + $len;
		if ( $newpos > 0x7fffffff ) {
			$this->throwException(
				'A value in the CDB file "' . $this->tmpFileName . '" is too large.' );
		}
		$this->pos = $newpos;
	}

	/**
	 * @param int $keylen
	 * @param int $datalen
	 * @param int $h
	 */
	protected function addend( $keylen, $datalen, $h ) {
		$this->hplist[] = [
			'h' => $h,
			'p' => $this->pos
		];

		$this->numentries++;
		$this->posplus( 8 );
		$this->posplus( $keylen );
		$this->posplus( $datalen );
	}

	/**
	 * @throws Exception
	 * @param int $keylen
	 * @param int $datalen
	 */
	protected function addbegin( $keylen, $datalen ) {
		if ( $keylen > 0x7fffffff ) {
			$this->throwException( 'Key length too long in file "' . $this->tmpFileName . '".' );
		}
		if ( $datalen > 0x7fffffff ) {
			$this->throwException( 'Data length too long in file "' . $this->tmpFileName . '".' );
		}
		$buf = pack( 'VV', $keylen, $datalen );
		$this->write( $buf );
	}

	/**
	 * @throws Exception
	 */
	protected function finish() {
		// Hack for DBA cross-check
		$this->hplist = array_reverse( $this->hplist );

		// Calculate the number of items that will be in each hashtable
		$counts = array_fill( 0, 256, 0 );
		foreach ( $this->hplist as $item ) {
			++$counts[255 & $item['h']];
		}

		// Fill in $starts with the *end* indexes
		$starts = [];
		$pos = 0;
		for ( $i = 0; $i < 256; ++$i ) {
			$pos += $counts[$i];
			$starts[$i] = $pos;
		}

		// Excessively clever and indulgent code to simultaneously fill $packedTables
		// with the packed hashtables, and adjust the elements of $starts
		// to actually point to the starts instead of the ends.
		if ( $this->numentries > 0 ) {
			$packedTables = array_fill( 0, $this->numentries, false );
		} else {
			// array_fill(): Number of elements must be positive
			$packedTables = [];
		}
		foreach ( $this->hplist as $item ) {
			$packedTables[--$starts[255 & $item['h']]] = $item;
		}

		$final = '';
		for ( $i = 0; $i < 256; ++$i ) {
			$count = $counts[$i];

			// The size of the hashtable will be double the item count.
			// The rest of the slots will be empty.
			$len = $count + $count;
			$final .= pack( 'VV', $this->pos, $len );

			$hashtable = [];
			for ( $u = 0; $u < $len; ++$u ) {
				$hashtable[$u] = [ 'h' => 0, 'p' => 0 ];
			}

			// Fill the hashtable, using the next empty slot if the hashed slot
			// is taken.
			for ( $u = 0; $u < $count; ++$u ) {
				$hp = $packedTables[$starts[$i] + $u];
				$where = Util::unsignedMod(
					Util::unsignedShiftRight( $hp['h'], 8 ), $len );
				while ( $hashtable[$where]['p'] ) {
					if ( ++$where == $len ) {
						$where = 0;
					}
				}
				$hashtable[$where] = $hp;
			}

			// Write the hashtable
			for ( $u = 0; $u < $len; ++$u ) {
				$buf = pack( 'vvV',
					$hashtable[$u]['h'] & 0xffff,
					Util::unsignedShiftRight( $hashtable[$u]['h'], 16 ),
					$hashtable[$u]['p'] );
				$this->write( $buf );
				$this->posplus( 8 );
			}
		}

		// Write the pointer array at the start of the file
		rewind( $this->handle );
		if ( ftell( $this->handle ) != 0 ) {
			$this->throwException( 'Error rewinding to start of file "' . $this->tmpFileName . '".' );
		}
		$this->write( $final );
	}

	/**
	 * Clean up the temp file and throw an exception
	 *
	 * @param string $msg
	 * @throws Exception
	 */
	protected function throwException( $msg ) {
		if ( $this->handle ) {
			fclose( $this->handle );
			unlink( $this->tmpFileName );
		}
		throw new Exception( $msg );
	}
}


<?php

namespace Cdb;

/**
 * Native CDB file reader and writer.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 */

/**
 * Read from a CDB file.
 * Native and pure PHP implementations are provided.
 * http://cr.yp.to/cdb.html
 */
abstract class Reader {
	/**
	 * The file handle
	 */
	protected $handle;

	/**
	 * Open a file and return a subclass instance
	 *
	 * @param string $fileName
	 * @return Reader
	 */
	public static function open( $fileName ) {
		return self::haveExtension() ?
			new Reader\DBA( $fileName ) :
			new Reader\PHP( $fileName );
	}

	/**
	 * Returns true if the native extension is available
	 *
	 * @return bool
	 * @codeCoverageIgnore
	 */
	public static function haveExtension() {
		if ( !function_exists( 'dba_handlers' ) ) {
			return false;
		}
		$handlers = dba_handlers();
		if ( !in_array( 'cdb', $handlers ) || !in_array( 'cdb_make', $handlers ) ) {
			return false;
		}

		return true;
	}

	/**
	 * Create the object and open the file
	 *
	 * @param string $fileName
	 */
	abstract public function __construct( $fileName );

	/**
	 * Close the file. Optional, you can just let the variable go out of scope.
	 */
	abstract public function close();

	/**
	 * Get a value with a given key. Only string values are supported.
	 *
	 * @param string $key
	 */
	abstract public function get( $key );

	/**
	 * Check whether key exists
	 *
	 * @param string $key
	 */
	abstract public function exists( $key );

	/**
	 * Fetch first key
	 */
	abstract public function firstkey();

	/**
	 * Fetch next key
	 */
	abstract public function nextkey();
}


<?php

namespace Cdb\Reader;

use Cdb\Exception;
use Cdb\Reader;
use Cdb\Util;

/**
 * This is a port of D.J. Bernstein's CDB to PHP. It's based on the copy that
 * appears in PHP 5.3.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 */

/**
 * CDB reader class
 */
class PHP extends Reader {

	/** @var string The file name of the CDB file. **/
	protected $fileName;

	/** @var string First 2048b of CDB file, containing pointers to hash table. **/
	protected $index;

	/** @var int Offset in file where value of found key starts. **/
	protected $dataPos;

	/** @var int Byte length of found key's value. **/
	protected $dataLen;

	/** @var int File position indicator when iterating over keys. **/
	protected $keyIterPos = 2048;

	/** @var int Offset in file where hash tables start. **/
	protected $keyIterStop;

	/** @var string Read buffer for CDB file. **/
	protected $buf;

	/** @var int File offset where read buffer starts. **/
	protected $bufStart;

	/** @var int File handle position indicator **/
	protected $filePos = 2048;

	/**
	 * Constructor.
	 *
	 * @param string $fileName
	 * @throws Exception If CDB file cannot be opened or if it contains fewer
	 *   than 2048 bytes of data.
	 */
	public function __construct( $fileName ) {
		$this->fileName = $fileName;
		$this->handle = fopen( $fileName, 'rb' );
		if ( !$this->handle ) {
			throw new Exception( 'Unable to open CDB file "' . $this->fileName . '".' );
		}
		$this->index = fread( $this->handle, 2048 );
		if ( strlen( $this->index ) !== 2048 ) {
			throw new Exception( 'CDB file contains fewer than 2048 bytes of data.' );
		}
	}

	/**
	 * Close the handle on the CDB file.
	 */
	public function close() {
		if ( isset( $this->handle ) ) {
			fclose( $this->handle );
		}
		unset( $this->handle );
	}

	/**
	 * Get the value of a key.
	 *
	 * @param mixed $key
	 * @return bool|string The key's value or false if not found.
	 */
	public function get( $key ) {
		// strval is required
		if ( $this->find( strval( $key ) ) ) {
			return $this->read( $this->dataPos, $this->dataLen );
		}

		return false;
	}

	/**
	 * Read data from the CDB file.
	 *
	 * @throws Exception When attempting to read past the end of the file.
	 * @param int $start Start reading from this position.
	 * @param int $len Number of bytes to read.
	 * @return string Read data.
	 */
	protected function read( $start, $len ) {
		$end = $start + $len;

		// The first 2048 bytes are the lookup table, which is read into
		// memory on initialization.
		if ( $end <= 2048 ) {
			return substr( $this->index, $start, $len );
		}

		// Read data from the internal buffer first.
		$bytes = '';
		if ( $this->buf && $start >= $this->bufStart ) {
			$bytes .= substr( $this->buf, $start - $this->bufStart, $len );
			$bytesRead = strlen( $bytes );
			$len -= $bytesRead;
			$start += $bytesRead;
		} else {
			$bytesRead = 0;
		}

		if ( !$len ) {
			return $bytes;
		}

		// Many reads are sequential, so the file position indicator may
		// already be in the right place, in which case we can avoid the
		// call to fseek().
		if ( $start !== $this->filePos ) {
			if ( fseek( $this->handle, $start ) === -1 ) {
				// This can easily happen if the internal pointers are incorrect
				throw new Exception(
					'Seek failed, file "' . $this->fileName . '" may be corrupted.' );
			}
		}

		$buf = fread( $this->handle, max( $len, 1024 ) );
		if ( $buf === false ) {
			$buf = '';
		}

		$bytes .= substr( $buf, 0, $len );
		if ( strlen( $bytes ) !== $len + $bytesRead ) {
			throw new Exception(
				'Read from CDB file failed, file "' . $this->fileName . '" may be corrupted.' );
		}

		$this->filePos = $end;
		$this->bufStart = $start;
		$this->buf = $buf;

		return $bytes;
	}

	/**
	 * Unpack an unsigned integer and throw an exception if it needs more than 31 bits.
	 *
	 * @param int $pos Position to read from.
	 * @throws Exception When the integer cannot be represented in 31 bits.
	 * @return int
	 */
	protected function readInt31( $pos = 0 ) {
		$uint31 = $this->readInt32( $pos );
		if ( $uint31 > 0x7fffffff ) {
			throw new Exception(
				'Error in CDB file "' . $this->fileName . '", integer too big.' );
		}

		return $uint31;
	}

	/**
	 * Unpack a 32-bit integer.
	 *
	 * @param int $pos
	 * @return int
	 */
	protected function readInt32( $pos = 0 ) {
		static $lookups;

		if ( !$lookups ) {
			$lookups = [];
			for ( $i = 1; $i < 256; $i++ ) {
				$lookups[ chr( $i ) ] = $i;
			}
		}

		$buf = $this->read( $pos, 4 );

		$rv = 0;

		if ( $buf[0] !== "\x0" ) {
			$rv = $lookups[ $buf[0] ];
		}
		if ( $buf[1] !== "\x0" ) {
			$rv |= ( $lookups[ $buf[1] ] << 8 );
		}
		if ( $buf[2] !== "\x0" ) {
			$rv |= ( $lookups[ $buf[2] ] << 16 );
		}
		if ( $buf[3] !== "\x0" ) {
			$rv |= ( $lookups[ $buf[3] ] << 24 );
		}

		return $rv;
	}

	/**
	 * Search the CDB file for a key.
	 *
	 * Sets `dataLen` and `dataPos` properties if successful.
	 *
	 * @param string $key
	 * @return bool Whether the key was found.
	 */
	protected function find( $key ) {
		$keyLen = strlen( $key );

		$u = Util::hash( $key );
		$upos = ( $u << 3 ) & 2047;
		$hashSlots = $this->readInt31( $upos + 4 );
		if ( !$hashSlots ) {
			return false;
		}
		$hashPos = $this->readInt31( $upos );
		$keyHash = $u;
		$u = Util::unsignedShiftRight( $u, 8 );
		$u = Util::unsignedMod( $u, $hashSlots );
		$u <<= 3;
		$keyPos = $hashPos + $u;

		for ( $i = 0; $i < $hashSlots; $i++ ) {
			$hash = $this->readInt32( $keyPos );
			$pos = $this->readInt31( $keyPos + 4 );
			if ( !$pos ) {
				return false;
			}
			$keyPos += 8;
			if ( $keyPos == $hashPos + ( $hashSlots << 3 ) ) {
				$keyPos = $hashPos;
			}
			if ( $hash === $keyHash ) {
				if ( $keyLen === $this->readInt31( $pos ) ) {
					$dataLen = $this->readInt31( $pos + 4 );
					$dataPos = $pos + 8 + $keyLen;
					$foundKey = $this->read( $pos + 8, $keyLen );
					if ( $foundKey === $key ) {
						// Found
						$this->dataLen = $dataLen;
						$this->dataPos = $dataPos;

						return true;
					}
				}
			}
		}

		return false;
	}

	/**
	 * Check if a key exists in the CDB file.
	 *
	 * @param string $key
	 * @return bool Whether the key exists.
	 */
	public function exists( $key ) {
		return $this->find( strval( $key ) );
	}

	/**
	 * Get the first key from the CDB file and reset the key iterator.
	 *
	 * @return string|bool Key, or false if no keys in file.
	 */
	public function firstkey() {
		$this->keyIterPos = 4;

		if ( !$this->keyIterStop ) {
			$pos = INF;
			for ( $i = 0; $i < 2048; $i += 8 ) {
				$pos = min( $this->readInt31( $i ), $pos );
			}
			$this->keyIterStop = $pos;
		}

		$this->keyIterPos = 2048;
		return $this->nextkey();
	}

	/**
	 * Get the next key from the CDB file.
	 *
	 * @return string|bool Key, or false if no more keys.
	 */
	public function nextkey() {
		if ( $this->keyIterPos >= $this->keyIterStop ) {
			return false;
		}
		$keyLen = $this->readInt31( $this->keyIterPos );
		$dataLen = $this->readInt31( $this->keyIterPos + 4 );
		$key = $this->read( $this->keyIterPos + 8, $keyLen );
		$this->keyIterPos += 8 + $keyLen + $dataLen;

		return $key;
	}
}


<?php

namespace Http\Adapter\React;

use React\EventLoop\LoopInterface;
use React\EventLoop\Factory as EventLoopFactory;
use React\Dns\Resolver\Resolver as DnsResolver;
use React\Dns\Resolver\Factory as DnsResolverFactory;
use React\HttpClient\Client as HttpClient;
use React\HttpClient\Factory as HttpClientFactory;
use React\Socket\Connector;
use React\Socket\ConnectorInterface;

/**
 * Factory wrapper for React instances.
 *
 * @author Stéphane Hulard <stephane@hlrd.me>
 */
class ReactFactory
{
    /**
     * Build a react Event Loop.
     *
     * @return LoopInterface
     */
    public static function buildEventLoop()
    {
        return EventLoopFactory::create();
    }

    /**
     * Build a React Dns Resolver.
     *
     * @param LoopInterface $loop
     * @param string        $dns
     *
     * @return DnsResolver
     */
    public static function buildDnsResolver(
        LoopInterface $loop,
        $dns = '8.8.8.8'
    ) {
        $factory = new DnsResolverFactory();

        return $factory->createCached($dns, $loop);
    }

    /**
     * @param LoopInterface    $loop
     * @param DnsResolver|null $dns
     *
     * @return ConnectorInterface
     */
    public static function buildConnector(
        LoopInterface $loop,
        DnsResolver $dns = null
    ) {
        return null !== $dns
            ? new Connector($loop, ['dns' => $dns])
            : new Connector($loop);
    }

    /**
     * Build a React Http Client.
     *
     * @param LoopInterface                       $loop
     * @param ConnectorInterface|DnsResolver|null $connector Only pass this argument if you need to customize DNS
     *                                                       behaviour. With react http client v0.5, pass a connector,
     *                                                       with v0.4 this must be a DnsResolver.
     *
     * @return HttpClient
     */
    public static function buildHttpClient(
        LoopInterface $loop,
        $connector = null
    ) {
        if (class_exists(HttpClientFactory::class)) {
            // if HttpClientFactory class exists, use old behavior for backwards compatibility
            return static::buildHttpClient04($loop, $connector);
        } else {
            return static::buildHttpClient05($loop, $connector);
        }
    }

    /**
     * Builds a React Http client v0.4 style.
     *
     * @param LoopInterface    $loop
     * @param DnsResolver|null $dns
     *
     * @return HttpClient
     */
    protected static function buildHttpClient04(
        LoopInterface $loop,
        $dns = null
    ) {
        // create dns resolver if one isn't provided
        if (null === $dns) {
            $dns = static::buildDnsResolver($loop);
        }

        // validate connector instance for proper error reporting
        if (!$dns instanceof DnsResolver) {
            throw new \InvalidArgumentException('For react http client v0.4, $dns must be an instance of DnsResolver');
        }

        $factory = new HttpClientFactory();

        return $factory->create($loop, $dns);
    }

    /**
     * Builds a React Http client v0.5 style.
     *
     * @param LoopInterface                       $loop
     * @param DnsResolver|ConnectorInterface|null $connector
     *
     * @return HttpClient
     */
    protected static function buildHttpClient05(
        LoopInterface $loop,
        $connector = null
    ) {
        // build a connector with given DnsResolver if provided (old deprecated behavior)
        if ($connector instanceof DnsResolver) {
            @trigger_error(
                sprintf(
                    'Passing a %s to buildHttpClient is deprecated since version 2.1.0 and will be removed in 3.0. If you need no specific behaviour, omit the $dns argument, otherwise pass a %s',
                    DnsResolver::class,
                    ConnectorInterface::class
                ),
                E_USER_DEPRECATED
            );
            $connector = static::buildConnector($loop, $connector);
        }

        // validate connector instance for proper error reporting
        if (null !== $connector && !$connector instanceof ConnectorInterface) {
            throw new \InvalidArgumentException(
                '$connector must be an instance of DnsResolver or ConnectorInterface'
            );
        }

        return new HttpClient($loop, $connector);
    }
}


<?php

namespace Cdb;

/**
 * This is a port of D.J. Bernstein's CDB to PHP. It's based on the copy that
 * appears in PHP 5.3. Changes are:
 *    * Error returns replaced with exceptions
 *    * Exception thrown if sizes or offsets are between 2GB and 4GB
 *    * Some variables renamed
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 * http://www.gnu.org/copyleft/gpl.html
 *
 * @file
 */

/**
 * Common functions for readers and writers
 */
class Util {
	/**
	 * Take a modulo of a signed integer as if it were an unsigned integer.
	 * $b must be less than 0x40000000 and greater than 0
	 *
	 * @param int $a
	 * @param int $b
	 *
	 * @return int
	 */
	public static function unsignedMod( $a, $b ) {
		if ( $a & 0x80000000 ) {
			$m = ( $a & 0x7fffffff ) % $b + 2 * ( 0x40000000 % $b );

			return $m % $b;
		} else {
			return $a % $b;
		}
	}

	/**
	 * Shift a signed integer right as if it were unsigned
	 * @param int $a
	 * @param int $b
	 * @return int
	 */
	public static function unsignedShiftRight( $a, $b ) {
		if ( $b == 0 ) {
			return $a;
		}
		if ( $a & 0x80000000 ) {
			return ( ( $a & 0x7fffffff ) >> $b ) | ( 0x40000000 >> ( $b - 1 ) );
		} else {
			return $a >> $b;
		}
	}

	/**
	 * The CDB hash function.
	 *
	 * @param string $s
	 *
	 * @return int
	 */
	public static function hash( $s ) {
		$h = 5381;
		$len = strlen( $s );
		for ( $i = 0; $i < $len; $i++ ) {
			$h5 = ( $h << 5 ) & 0xffffffff;
			// Do a 32-bit sum
			// Inlined here for speed
			$sum = ( $h & 0x3fffffff ) + ( $h5 & 0x3fffffff );
			$h =
				(
					( $sum & 0x40000000 ? 1 : 0 )
					+ ( $h & 0x80000000 ? 2 : 0 )
					+ ( $h & 0x40000000 ? 1 : 0 )
					+ ( $h5 & 0x80000000 ? 2 : 0 )
					+ ( $h5 & 0x40000000 ? 1 : 0 )
				) << 30
				| ( $sum & 0x3fffffff );
			$h ^= ord( $s[$i] );
			$h &= 0xffffffff;
		}

		return $h;
	}
}


<?php

namespace Http\Adapter\React;

use Http\Client\HttpClient;
use Http\Client\HttpAsyncClient;
use Http\Client\Exception\HttpException;
use Http\Client\Exception\RequestException;
use Http\Discovery\MessageFactoryDiscovery;
use Http\Discovery\StreamFactoryDiscovery;
use Http\Message\ResponseFactory;
use Http\Message\StreamFactory;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use React\EventLoop\LoopInterface;
use React\HttpClient\Client as ReactClient;
use React\HttpClient\Request as ReactRequest;
use React\HttpClient\Response as ReactResponse;

/**
 * Client for the React promise implementation.
 *
 * @author Stéphane Hulard <stephane@hlrd.me>
 */
class Client implements HttpClient, HttpAsyncClient
{
    /**
     * React HTTP client.
     *
     * @var Client
     */
    private $client;

    /**
     * React event loop.
     *
     * @var LoopInterface
     */
    private $loop;

    /**
     * @var ResponseFactory
     */
    private $responseFactory;

    /**
     * @var StreamFactory
     */
    private $streamFactory;

    /**
     * Initialize the React client.
     *
     * @param ResponseFactory|null $responseFactory
     * @param LoopInterface|null   $loop
     * @param ReactClient|null     $client
     * @param StreamFactory|null   $streamFactory
     */
    public function __construct(
        ResponseFactory $responseFactory = null,
        LoopInterface $loop = null,
        ReactClient $client = null,
        StreamFactory $streamFactory = null
    ) {
        if (null !== $client && null === $loop) {
            throw new \RuntimeException(
                'You must give a LoopInterface instance with the Client'
            );
        }

        $this->loop = $loop ?: ReactFactory::buildEventLoop();
        $this->client = $client ?: ReactFactory::buildHttpClient($this->loop);

        $this->responseFactory = $responseFactory ?: MessageFactoryDiscovery::find();
        $this->streamFactory = $streamFactory ?: StreamFactoryDiscovery::find();
    }

    /**
     * {@inheritdoc}
     */
    public function sendRequest(RequestInterface $request)
    {
        $promise = $this->sendAsyncRequest($request);

        return $promise->wait();
    }

    /**
     * {@inheritdoc}
     */
    public function sendAsyncRequest(RequestInterface $request)
    {
        $reactRequest = $this->buildReactRequest($request);
        $promise = new Promise($this->loop);

        $reactRequest->on('error', function (\Exception $error) use ($promise, $request) {
            $promise->reject(new RequestException(
                $error->getMessage(),
                $request,
                $error
            ));
        });

        $reactRequest->on('response', function (ReactResponse $reactResponse = null) use ($promise, $request) {
            $bodyStream = $this->streamFactory->createStream();
            $reactResponse->on('data', function ($data) use (&$bodyStream) {
                $bodyStream->write((string) $data);
            });

            $reactResponse->on('end', function (\Exception $error = null) use ($promise, $request, $reactResponse, &$bodyStream) {
                $response = $this->buildResponse(
                    $reactResponse,
                    $bodyStream
                );
                if (null !== $error) {
                    $promise->reject(new HttpException(
                        $error->getMessage(),
                        $request,
                        $response,
                        $error
                    ));
                } else {
                    $promise->resolve($response);
                }
            });
        });

        $reactRequest->end((string) $request->getBody());

        return $promise;
    }

    /**
     * Build a React request from the PSR7 RequestInterface.
     *
     * @param RequestInterface $request
     *
     * @return ReactRequest
     */
    private function buildReactRequest(RequestInterface $request)
    {
        $headers = [];

        foreach ($request->getHeaders() as $name => $value) {
            $headers[$name] = (is_array($value) ? $value[0] : $value);
        }

        $reactRequest = $this->client->request(
            $request->getMethod(),
            (string) $request->getUri(),
            $headers,
            $request->getProtocolVersion()
        );

        return $reactRequest;
    }

    /**
     * Transform a React Response to a valid PSR7 ResponseInterface instance.
     *
     * @param ReactResponse   $response
     * @param StreamInterface $body
     *
     * @return ResponseInterface
     */
    private function buildResponse(
        ReactResponse $response,
        StreamInterface $body
    ) {
        $body->rewind();

        return $this->responseFactory->createResponse(
            $response->getCode(),
            $response->getReasonPhrase(),
            $response->getHeaders(),
            $body,
            $response->getVersion()
        );
    }
}


<?php
namespace Lukeed\Theme;

use Lukeed\Theme\Exceptions\ThemeNotFoundException;
use Illuminate\Contracts\Container\Container;
use Lukeed\Theme\Exceptions\ThemeInfoAttributeException;
use Lukeed\Theme\Contracts\ThemeInterface;

/**
 * Theme
 *
 * @author Karlo Mikuš
 * @author Luke Edwards
 * @version 1.0.3
 * @package Lukeed\Theme
 */
class Theme implements ThemeInterface
{
    /**
     * Scanned themes
     * @var array|ThemeInfo[]
     */
    private $themes;

    /**
     * View finder
     * @var \Illuminate\View\Factory
     */
    private $view;

    /**
     * Base theme folder
     * @var string
     */
    private $basePath;

    /**
     * Current active theme
     * @var string|null
     */
    private $activeTheme = null;

    /**
     * Setup default view finder and view paths.
     *
     * @param Container $app
     */
    public function __construct(Container $app)
    {
        // Default themes path
        $this->basePath = config('theme.path');

        // Config view finder
        $paths = $app['config']['view.paths'];
        $this->view = $app->make('view');
        $this->view->setFinder(new ThemeViewFinder($app['files'], (array) $paths));

        // Scan themes
        $this->scanThemes();
    }

    /**
     * Set current active theme
     *
     * @param string $theme Theme directory
     * @throws ThemeNotFoundException
     */
    public function set($theme)
    {
        if (!$this->has($theme)) {
            throw new ThemeNotFoundException($theme);
        }

        $this->loadTheme($theme);
    }

    /**
     * Get all found themes
     *
     * @return array|ThemeInfo[]
     */
    public function all()
    {
        return $this->themes;
    }

    /**
     * @depracted Use all() method
     */
    public function getThemes()
    {
        return $this->all();
    }

    /**
     * Returns theme information.
     *
     * @param string Theme directory
     * @return null|ThemeInfo
     */
    public function get($theme = null)
    {
        if (is_null($theme)) {
            return $this->themes[$this->activeTheme];
        }

        return $this->themes[$theme];
    }

    /**
     * Check if theme exists
     *
     * @param $theme
     * @return bool
     */
    public function has($theme)
    {
        return array_key_exists($theme, $this->themes);
    }

    /**
     * @depracted Use has() method
     */
    public function themeExists($theme)
    {
        return $this->has($theme);
    }

    /**
     * Set base themes folder path
     *
     * @param $path
     */
    public function setDefaultThemePath($path)
    {
        $this->basePath = $path;
        $this->scanThemes();
    }

    /**
     * Load a theme
     *
     * @param string $theme
     * @throws \Exception
     */
    private function loadTheme($theme)
    {
        if (!isset($theme)) {
            return;
        }

        $th = $this->findThemeByDirectory($theme);

        if (isset($th)) {
            $viewFinder = $this->view->getFinder();

            $viewFinder->prependPath($th->getPath());
            if (!is_null($th->getParent())) {
                $this->loadTheme($th->getParent());
            }

            $this->activeTheme = $theme;
        }
    }

    /**
     * Find a theme from all scanned themes
     *
     * @param string $directory
     * @return null|ThemeInfo
     */
    private function findThemeByDirectory($directory)
    {
        if (isset($this->themes[$directory])) {
            return $this->themes[$directory];
        }

        return null;
    }

    /**
     * Scan for all available themes
     *
     * @throws ThemeInfoAttributeException
     */
    private function scanThemes()
    {
        $themeDirectories = glob($this->basePath . '/*', GLOB_ONLYDIR);

        $themes = [];
        foreach ($themeDirectories as $themePath) {
            $json = $themePath . '/theme.json';

            if (file_exists($json)) {
                $contents = file_get_contents($json);
                if (!$contents === false) {
                    $th = $this->parseThemeInfo(json_decode($contents, true));
                    $themes[$th->getDirectory()] = $th;
                }
            }
        }

        $this->themes = $themes;

        // if no active theme & if found 1+ theme, set first as default
        if (count($themes) && !$this->activeTheme) {
            $this->set(array_keys($themes)[0]);
        }
    }

    /**
     * Find theme views path
     *
     * @param $directory
     * @return string
     */
    private function findPath($directory)
    {
        $path = [];
        $path[] = $this->basePath;
        $path[] = $directory;
        $path[] = 'views';

        return implode(DIRECTORY_SEPARATOR, $path);
    }

    /**
     * Parse theme json file
     *
     * @param array $info
     * @return ThemeInfoInterface
     * @throws ThemeInfoAttributeException
     */
    private function parseThemeInfo(array $info)
    {
        $themeInfo = new ThemeInfo();

        $required = ['name', 'author', 'directory'];
        foreach ($required as $key) {
            if (!array_key_exists($key, $info)) {
                throw new ThemeInfoAttributeException($key);
            }
        }

        $themeInfo->setName($info['name']);
        $themeInfo->setAuthor($info['author']);
        $themeInfo->setDirectory(strtolower($info['directory']));

        if (isset($info['description'])) {
            $themeInfo->setDescription($info['description']);
        }
        if (isset($info['version'])) {
            $themeInfo->setVersion($info['version']);
        }
        if (isset($info['parent'])) {
            $themeInfo->setParent($info['parent']);
        }

        $themeInfo->setPath($this->findPath($info['directory']));

        return $themeInfo;
    }
}


<?php declare(strict_types=1); # -*- coding: utf-8 -*-
/*
 * This file is part of the Assets package.
 *
 * (c) Inpsyde GmbH
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Inpsyde\Assets;

class AssetHookResolver
{

    /**
     * Resolving to the current location/page in WordPress all current Hooks
     *
     * @return array
     */
    public function resolve(): array
    {
        $pageNow = $GLOBALS['pagenow'] ?? '';
        $pageNow = basename($pageNow);

        $isCore = defined('ABSPATH');
        $isAjax = $isCore
            ? wp_doing_ajax()
            : false;
        $isAdmin = $isCore
            ? is_admin() && ! $isAjax
            : false;
        $isCron = $isCore
            ? wp_doing_cron()
            : false;
        $isLogin = ($pageNow === 'wp-login.php');
        $isPostEdit = ($pageNow === 'post.php') || ($pageNow === 'post-new.php');
        $isCli = defined('WP_CLI');
        $isFront = ! $isAdmin && ! $isAjax && ! $isCron && ! $isLogin && ! $isCli;
        $isCustomizer = is_customize_preview();

        $hooks = [];

        if ($isAjax) {
            return [];
        }

        if ($isLogin) {
            $hooks[] = Asset::HOOK_LOGIN;
        }

        if ($isPostEdit) {
            $hooks[] = Asset::HOOK_BLOCK_EDITOR_ASSETS;
        }

        if ($isFront) {
            $hooks[] = Asset::HOOK_FRONTEND;
        }

        if ($isCustomizer) {
            $hooks[] = Asset::HOOK_CUSTOMIZER;
        }

        if ($isAdmin) {
            $hooks[] = Asset::HOOK_BACKEND;
        }

        return $hooks;
    }
}


<?php declare(strict_types=1); # -*- coding: utf-8 -*-
/*
 * This file is part of the Assets package.
 *
 * (c) Inpsyde GmbH
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Inpsyde\Assets;

final class AssetFactory
{

    /**
     * @param array $config
     *
     * @return Asset
     * @throws Exception\MissingArgumentException
     * @throws Exception\InvalidArgumentException
     */
    public static function create(array $config): Asset
    {
        $config = self::migrateConfig($config);

        self::validateConfig($config);

        $location = $config['location'] ?? Asset::FRONTEND;
        $handle = $config['handle'];
        $url = $config['url'];
        $class = (string) $config['type'];

        $asset = new $class($handle, $url, $location, $config);

        if (! $asset instanceof Asset) {
            throw new Exception\InvalidArgumentException(
                sprintf(
                    'The given class "%s" is not implementing %s',
                    $class,
                    Asset::class
                )
            );
        }

        return $asset;
    }

    /**
     * Migration of old config "type" => "location", "class" => "type" definition.
     *
     * @example [ 'type' => Asset::FRONTEND, 'class' => Script::class ]
     *          => [ 'location' => Asset::FRONTEND, 'type' => Script::class ]
     *
     * @since 1.1
     *
     * @param array $config
     *
     * @return array
     */
    private static function migrateConfig(array $config): array
    {
        // if old format "type" and "class" is set, migrate.
        if (isset($config['class'])) {
            do_action(
                'inpsyde.assets.debug',
                'The asset config-format with "type" and "class" is deprecated.',
                $config
            );

            $config['location'] = $config['type'] ?? Asset::FRONTEND;
            $config['type'] = $config['class'];

            unset($config['class']);
        }

        return $config;
    }

    /**
     * @param array $config
     *
     * @throws Exception\MissingArgumentException
     */
    private static function validateConfig(array $config)
    {
        $requiredFields = [
            'type',
            'url',
            'handle',
        ];

        foreach ($requiredFields as $key) {
            if (! isset($config[$key])) {
                throw new Exception\MissingArgumentException(
                    sprintf(
                        'The given config <code>%s</code> is missing.',
                        $key
                    )
                );
            }
        }
    }

    /**
     * @param string $file
     *
     * @return array
     * @throws Exception\FileNotFoundException
     */
    public static function createFromFile(string $file): array
    {
        if (! file_exists($file)) {
            throw new Exception\FileNotFoundException(
                sprintf(
                    'The given file "%s" does not exists.',
                    $file
                )
            );
        }

        $data = include_once $file;

        return self::createFromArray($data);
    }

    public static function createFromArray(array $data): array
    {
        return array_map(
            [
                __CLASS__,
                'create',
            ],
            $data
        );
    }
}


<?php

/*
 * This file is part of Laravel Navigation.
 *
 * (c) Graham Campbell <graham@alt-three.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace GrahamCampbell\Navigation;

use Illuminate\Support\ServiceProvider;

/**
 * This is the navigation service provider class.
 *
 * @author Graham Campbell <graham@alt-three.com>
 */
class NavigationServiceProvider extends ServiceProvider
{
    /**
     * Boot the service provider.
     *
     * @return void
     */
    public function boot()
    {
        $this->loadViewsFrom(realpath(__DIR__.'/../views'), 'navigation');
    }

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->registerNavigation();
    }

    /**
     * Register the navigation class.
     *
     * @return void
     */
    protected function registerNavigation()
    {
        $this->app->singleton('navigation', function ($app) {
            $request = $app['request'];
            $events = $app['events'];
            $url = $app['url'];
            $view = $app['view'];
            $name = 'navigation::bootstrap';

            $navigation = new Navigation($request, $events, $url, $view, $name);
            $app->refresh('request', $navigation, 'setRequest');

            return $navigation;
        });

        $this->app->alias('navigation', Navigation::class);
    }

    /**
     * Get the services provided by the provider.
     *
     * @return string[]
     */
    public function provides()
    {
        return [
            'navigation',
        ];
    }
}


<?php

/*
 * This file is part of Laravel Navigation.
 *
 * (c) Graham Campbell <graham@alt-three.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace GrahamCampbell\Navigation;

use Illuminate\Contracts\Events\Dispatcher;
use Illuminate\Contracts\Routing\UrlGenerator;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request;

/**
 * This is the navigation class.
 *
 * @author Graham Campbell <graham@alt-three.com>
 */
class Navigation
{
    /**
     * The items in the main nav bar.
     *
     * @var array
     */
    protected $main = [];

    /**
     * The items in the bar nav bar.
     *
     * @var array
     */
    protected $bar = [];

    /**
     * The request instance.
     *
     * @var \Illuminate\Http\Request
     */
    protected $request;

    /**
     * The events instance.
     *
     * @var \Illuminate\Contracts\Events\Dispatcher
     */
    protected $events;

    /**
     * The url instance.
     *
     * @var \Illuminate\Contracts\Routing\UrlGenerator
     */
    protected $url;

    /**
     * The view instance.
     *
     * @var \Illuminate\Contracts\View\Factory
     */
    protected $view;

    /**
     * The view name.
     *
     * @var string
     */
    protected $name;

    /**
     * Create a new instance.
     *
     * @param \Illuminate\Http\Request                   $request
     * @param \Illuminate\Contracts\Events\Dispatcher    $events
     * @param \Illuminate\Contracts\Routing\UrlGenerator $url
     * @param \Illuminate\Contracts\View\Factory         $view
     * @param string                                     $name
     *
     * @return void
     */
    public function __construct(Request $request, Dispatcher $events, UrlGenerator $url, Factory $view, $name)
    {
        $this->request = $request;
        $this->events = $events;
        $this->url = $url;
        $this->view = $view;
        $this->name = $name;
    }

    /**
     * Add an item to the main navigation array.
     *
     * @param array  $item
     * @param string $name
     * @param bool   $first
     *
     * @return $this
     */
    public function addToMain(array $item, $name = 'default', $first = false)
    {
        // check if the name exists in the main array
        if (!array_key_exists($name, $this->main)) {
            // add it if it doesn't exists
            $this->main[$name] = [];
        }

        // check if we are forcing the item to the start
        if ($first) {
            // add the item to the start of the array
            $this->main[$name] = array_merge([$item], $this->main[$name]);
        } else {
            // add the item to the end of the array
            $this->main[$name][] = $item;
        }

        return $this;
    }

    /**
     * Add an item to the bar navigation array.
     *
     * @param array  $item
     * @param string $name
     * @param bool   $first
     *
     * @return $this
     */
    public function addToBar(array $item, $name = 'default', $first = false)
    {
        // check if the name exists in the bar array
        if (!array_key_exists($name, $this->bar)) {
            // add it if it doesn't exists
            $this->bar[$name] = [];
        }

        // check if we are forcing the item to the start
        if ($first) {
            // add the item to the start of the array
            $this->bar[$name] = array_merge([$item], $this->bar[$name]);
        } else {
            // add the item to the end of the array
            $this->bar[$name][] = $item;
        }

        return $this;
    }

    /**
     * Get the navigation bar html.
     *
     * @param string      $mainName
     * @param string|bool $barName
     * @param array|null  $data
     *
     * @return string
     */
    public function render($mainName = 'default', $barName = false, array $data = null)
    {
        // set the default value if nothing was passed
        if ($data === null) {
            $data = ['title' => 'Navigation', 'side' => 'dropdown', 'inverse' => true];
        }

        // get the nav bar arrays
        $main = $this->getMain($mainName);
        if (is_string($barName)) {
            $bar = $this->getBar($barName);
            if (empty($bar)) {
                $bar = false;
            }
        } else {
            $bar = false;
        }

        // return the html nav bar
        return $this->view->make($this->name, array_merge($data, ['main' => $main, 'bar' => $bar]))->render();
    }

    /**
     * Get the main navigation array.
     *
     * @param string $name
     *
     * @return array
     */
    protected function getMain($name = 'default')
    {
        // fire event that can be hooked to add items to the nav bar
        $this->events->fire('navigation.main', [['name' => $name]]);

        // check if the name exists in the main array
        if ($name !== 'default' && !array_key_exists($name, $this->main)) {
            // use the default name
            $name = 'default';
        }

        if (!array_key_exists($name, $this->main)) {
            // add it if it doesn't exists
            $this->main[$name] = [];
        }

        // apply active keys
        $nav = $this->active($this->main[$name]);

        // fix up and spit out the nav bar
        return $this->process($nav);
    }

    /**
     * Get the bar navigation array.
     *
     * @param string $name
     *
     * @return array
     */
    protected function getBar($name = 'default')
    {
        // fire event that can be hooked to add items to the nav bar
        $this->events->fire('navigation.bar', [['name' => $name]]);

        // check if the name exists in the bar array
        if ($name !== 'default' && !array_key_exists($name, $this->bar)) {
            // use the default name
            $name = 'default';
        }

        if (!array_key_exists($name, $this->bar)) {
            // add it if it doesn't exists
            $this->bar[$name] = [];
        }

        // don't apply active keys
        $nav = $this->bar[$name];

        // fix up and spit out the nav bar
        return $this->process($nav);
    }

    /**
     * Check if each item is active.
     *
     * @param array $nav
     *
     * @return array
     */
    protected function active(array $nav)
    {
        // check if each item is active
        foreach ($nav as $key => $value) {
            // check if it is local
            if (isset($value['slug'])) {
                // if the request starts with the slug
                if ($this->request->is($value['slug']) || $this->request->is($value['slug'].'/*')) {
                    // then the navigation item is active, or selected
                    $nav[$key]['active'] = true;
                } else {
                    // then the navigation item is not active or selected
                    $nav[$key]['active'] = false;
                }
            } else {
                // then the navigation item is not active or selected
                $nav[$key]['active'] = false;
            }
        }

        // spit out the nav bar array at the end
        return $nav;
    }

    /**
     * Convert slugs to urls.
     *
     * @param array $nav
     *
     * @return array
     */
    protected function process(array $nav)
    {
        // convert slugs to urls
        foreach ($nav as $key => $value) {
            // if the url is not set
            if (!isset($value['url'])) {
                // set the url based on the slug
                $nav[$key]['url'] = $this->url->to($value['slug']);
            }
            // remove any remaining slugs
            unset($nav[$key]['slug']);
        }

        // spit out the nav bar array at the end
        return $nav;
    }

    /**
     * Get the request instance.
     *
     * @return \Illuminate\Http\Request
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * Set the request instance.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return void
     */
    public function setRequest(Request $request)
    {
        $this->request = $request;
    }

    /**
     * Get the events instance.
     *
     * @return \Illuminate\Contracts\Events\Dispatcher
     */
    public function getEvents()
    {
        return $this->events;
    }

    /**
     * Get the url instance.
     *
     * @return \Illuminate\Contracts\Routing\UrlGenerator
     */
    public function getUrl()
    {
        return $this->url;
    }

    /**
     * Get the view instance.
     *
     * @return \Illuminate\Contracts\View\Factory
     */
    public function getView()
    {
        return $this->view;
    }
}


<?php

namespace deka6pb\geocoder;

use Location\Coordinate;
use Location\Distance\DistanceInterface;
use Location\Distance\Vincenty;

/**
 * Class Point
 * @package deka6pb\yii2-geocoder
 *
 * @property double $latitude
 * @property double $longitude
 */
class Point extends \yii\base\BaseObject
{
    /**
     * @var DistanceInterface
     */
    protected static $_calculator;

    /**
     * @var double
     */
    protected $latitude;

    /**
     * @var double
     */
    protected $longitude;

    /**
     * Returns latitude
     *
     * @return string
     */
    public function getLatitude()
    {
        return $this->latitude;
    }

    /**
     * Returns longitude
     *
     * @return string
     */
    public function getLongitude()
    {
        return $this->longitude;
    }

    /**
     * @param mixed $latitude
     */
    public function setLatitude($latitude)
    {
        $this->latitude = $latitude;
    }

    /**
     * @param mixed $longitude
     */
    public function setLongitude($longitude)
    {
        $this->longitude = $longitude;
    }

    /**
     * Returns distance between points in meters
     *
     * @param Point $point
     * @param DistanceInterface $calculator
     *
     * @return float
     */
    public function getDistance(Point $point, DistanceInterface $calculator = null)
    {
        $calculator = $calculator ? : static::getCalculator();

        return $calculator->getDistance(
            new Coordinate($this->latitude, $this->longitude),
            new Coordinate($point->latitude, $point->longitude)
        );
    }

    /**
     * Format coordinates to string
     *
     * @return string
     */
    public function toString()
    {
        return  $this->longitude . ',' . $this->latitude;
    }

    /**
     * Returns calculator instance
     *
     * @return \Location\Distance\DistanceInterface
     */
    protected static function getCalculator()
    {
        if (static::$_calculator === null) {
            static::$_calculator = new Vincenty();
        }

        return static::$_calculator;
    }

}


<?php

/*
 * This file is part of Simplex.
 *
 * Copyright (c) 2009 Fabien Potencier
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

namespace Simplex;

use Interop\Container\ServiceProviderInterface;
use Psr\Container\ContainerInterface;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Simplex\Exception\EntryNotFound;

/**
 * Container main class.
 *
 * @author Fabien Potencier
 * @author Matthieu Napoli <matthieu@mnapoli.fr>
 */
class Container implements \ArrayAccess, ContainerInterface
{
    private $values = array();
    private $factories;
    private $protected;
    private $frozen = array();
    private $raw = array();
    private $keys = array();

    /**
     * Container from which to fetch dependencies.
     * @see https://github.com/container-interop/container-interop/blob/master/docs/Delegate-lookup.md
     * @var ContainerInterface
     */
    private $rootContainer;

    /**
     * Instantiate the container.
     *
     * Objects and parameters can be passed as argument to the constructor.
     *
     * @param array $providers The service providers to register.
     * @param array $values The parameters or objects.
     * @param ContainerInterface $rootContainer Container from which to fetch dependencies. If null, this container
     *                                          will be considered the root container.
     */
    public function __construct(array $providers = array(), array $values = array(), ContainerInterface $rootContainer = null)
    {
        $this->rootContainer = $rootContainer ?: $this;
        $this->factories = new \SplObjectStorage();
        $this->protected = new \SplObjectStorage();

        $this->register($providers, $values);
    }

    /**
     * Finds an entry of the container by its identifier and returns it.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @throws NotFoundExceptionInterface  No entry was found for this identifier.
     * @throws ContainerExceptionInterface Error while retrieving the entry.
     *
     * @return mixed Entry.
     */
    public function get($id)
    {
        return $this->offsetGet($id);
    }

    /**
     * Returns true if the container can return an entry for the given identifier.
     * Returns false otherwise.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @return boolean
     */
    public function has($id)
    {
        return $this->offsetExists($id);
    }

    /**
     * Sets a parameter or an object.
     *
     * Objects must be defined as Closures.
     *
     * Allowing any PHP callable leads to difficult to debug problems
     * as function names (strings) are callable (creating a function with
     * the same name as an existing parameter would break your container).
     *
     * @param string $id    The unique identifier for the parameter or object
     * @param mixed  $value The value of the parameter or a closure to define an object
     *
     * @throws \RuntimeException Prevent override of a frozen service
     */
    public function set($id, $value)
    {
        $this->offsetSet($id, $value);
    }

    /**
     * Sets a parameter or an object.
     *
     * Objects must be defined as Closures.
     *
     * Allowing any PHP callable leads to difficult to debug problems
     * as function names (strings) are callable (creating a function with
     * the same name as an existing parameter would break your container).
     *
     * @param string $id    The unique identifier for the parameter or object
     * @param mixed  $value The value of the parameter or a closure to define an object
     *
     * @throws \RuntimeException Prevent override of a frozen service
     */
    public function offsetSet($id, $value)
    {
        if (isset($this->frozen[$id])) {
            throw new \RuntimeException(sprintf('Cannot override frozen service "%s".', $id));
        }

        $this->values[$id] = $value;
        $this->keys[$id] = true;
    }

    /**
     * Gets a parameter or an object.
     *
     * @param string $id The unique identifier for the parameter or object
     *
     * @return mixed The value of the parameter or an object
     *
     * @throws NotFoundExceptionInterface if the identifier is not defined
     */
    public function offsetGet($id)
    {
        if (!isset($this->keys[$id])) {
            throw new EntryNotFound($id);
        }

        if (
            isset($this->raw[$id])
            || !is_object($this->values[$id])
            || isset($this->protected[$this->values[$id]])
            || !method_exists($this->values[$id], '__invoke')
        ) {
            return $this->values[$id];
        }

        if (isset($this->factories[$this->values[$id]])) {
            return $this->values[$id]($this);
        }

        $raw = $this->values[$id];
        $val = $this->values[$id] = $raw($this->rootContainer);
        $this->raw[$id] = $raw;

        $this->frozen[$id] = true;

        return $val;
    }

    /**
     * Checks if a parameter or an object is set.
     *
     * @param string $id The unique identifier for the parameter or object
     *
     * @return bool
     */
    public function offsetExists($id)
    {
        return isset($this->keys[$id]);
    }

    /**
     * Unsets a parameter or an object.
     *
     * @param string $id The unique identifier for the parameter or object
     */
    public function offsetUnset($id)
    {
        if (isset($this->keys[$id])) {
            if (is_object($this->values[$id])) {
                unset($this->factories[$this->values[$id]], $this->protected[$this->values[$id]]);
            }

            unset($this->values[$id], $this->frozen[$id], $this->raw[$id], $this->keys[$id]);
        }
    }

    /**
     * Marks a callable as being a factory service.
     *
     * @param callable $callable A service definition to be used as a factory
     *
     * @return callable The passed callable
     *
     * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object
     */
    public function factory($callable)
    {
        if (!method_exists($callable, '__invoke')) {
            throw new \InvalidArgumentException('Service definition is not a Closure or invokable object.');
        }

        $this->factories->attach($callable);

        return $callable;
    }

    /**
     * Protects a callable from being interpreted as a service.
     *
     * This is useful when you want to store a callable as a parameter.
     *
     * @param callable $callable A callable to protect from being evaluated
     *
     * @return callable The passed callable
     *
     * @throws \InvalidArgumentException Service definition has to be a closure of an invokable object
     */
    public function protect($callable)
    {
        if (!method_exists($callable, '__invoke')) {
            throw new \InvalidArgumentException('Callable is not a Closure or invokable object.');
        }

        $this->protected->attach($callable);

        return $callable;
    }

    /**
     * Gets a parameter or the closure defining an object.
     *
     * @param string $id The unique identifier for the parameter or object
     *
     * @return mixed The value of the parameter or the closure defining an object
     *
     * @throws \InvalidArgumentException if the identifier is not defined
     */
    public function raw($id)
    {
        if (!isset($this->keys[$id])) {
            throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
        }

        if (isset($this->raw[$id])) {
            return $this->raw[$id];
        }

        return $this->values[$id];
    }

    /**
     * Extends an object definition.
     *
     * Useful when you want to extend an existing object definition,
     * without necessarily loading that object.
     *
     * @param string   $id       The unique identifier for the object
     * @param callable $callable A service definition to extend the original
     *
     * @return callable The wrapped callable
     *
     * @throws \InvalidArgumentException if the identifier is not defined or not a service definition
     */
    public function extend($id, $callable)
    {
        if (!isset($this->keys[$id])) {
            throw new \InvalidArgumentException(sprintf('Identifier "%s" is not defined.', $id));
        }

        if (!is_object($callable) || !method_exists($callable, '__invoke')) {
            throw new \InvalidArgumentException('Extension service definition is not a Closure or invokable object.');
        }

        $factory = $this->values[$id];

        $extended = function ($c) use ($callable, $factory) {
            $previous = is_callable($factory) ? $factory($c) : $factory;
            return $callable($previous, $c);
        };

        if (is_object($factory) && isset($this->factories[$factory])) {
            $this->factories->detach($factory);
            $this->factories->attach($extended);
        }

        return $this[$id] = $extended;
    }

    /**
     * Returns all defined value names.
     *
     * @return array An array of value names
     */
    public function keys()
    {
        return array_keys($this->values);
    }

    /**
     * Registers service providers.
     *
     * @param array $providers the list of service providers to register
     * @param array $values An array of values that customizes the providers
     *
     * @return void
     */
    private function register(array $providers, array $values)
    {
        foreach ($providers as $provider) {

            $factories = $provider->getFactories();

            foreach ($factories as $key => $callable) {
                $this[$key] = function (ContainerInterface $c) use ($callable) {
                    return call_user_func($callable, $c);
                };
            }

        }

        foreach ($providers as $provider) {

            $extensions = $provider->getExtensions();

            foreach ($extensions as $key => $callable) {

                if (isset($this->keys[$key])) {
                    // Extend a previous entry
                    $this[$key] = $this->extend($key, function ($previous, ContainerInterface $c) use ($callable) {
                        return call_user_func($callable, $c, $previous);
                    });
                } else {
                    $this[$key] = function (ContainerInterface $c) use ($callable) {
                        return call_user_func($callable, $c);
                    };
                }
            }

        }

        foreach ($values as $key => $value) {
            $this[$key] = $value;
        }
    }
}


<?php
namespace Rentgen\Schema\Manipulation;

use Rentgen\Database\Constraint\ConstraintInterface;
use Rentgen\Schema\Command;

class DropConstraintCommand extends Command
{
    private $constraint;

    /**
     * Set a constraint.
     *
     * @param ConstraintInterface $constraint The constraint instance.
     *
     * @return DropConstraintCommand
     */
    public function setConstraint(ConstraintInterface $constraint)
    {
        $this->constraint = $constraint;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getSql()
    {
        $sql = sprintf('ALTER TABLE %s DROP CONSTRAINT %s;'
            , $this->constraint->getTable()->getQualifiedName()
            , $this->constraint->getName()
        );

        return $sql;
    }
}


<?php
namespace Rentgen\Schema\Manipulation;

use Rentgen\Schema\Command;
use Rentgen\Database\Table;
use Rentgen\Schema\Adapter\Postgres\Info\GetTablesCommand;

class DropAllTablesCommand extends Command
{
    private $schemaName = 'public';
    private $sql = '';

    /**
     * Sets a schema name.
     *
     * @param string $schemaName The schema name.
     *
     * @return DropAllTablesCommand
     */
    public function setSchemaName($schemaName)
    {
        $this->schemaName = $schemaName;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getSql()
    {
        return $this->sql;
    }

    /**
     * {@inheritdoc}
     */
    public function execute()
    {
        $getTablesCommand = new GetTablesCommand();
        $getTablesCommand->setConnection($this->connection);
        $tables = $getTablesCommand->execute();

        $this->preExecute();
        foreach ($tables as $table) {
            $dropTable = new DropTableCommand();
            $dropTable
                ->setTable($table)
                ->cascade()
                ->setConnection($this->connection)
                ->setEventDispatcher($this->dispatcher);
            $this->sql .= $dropTable->getSql();
            $dropTable->execute();
        }
        $this->postExecute();

        return true;
    }
}


<?php
namespace Rentgen\Schema\Manipulation;

use Rentgen\Schema\Command;
use Rentgen\Database\Column;
use Rentgen\Database\Column\CustomColumn;
use Rentgen\Event\ColumnEvent;
use Rentgen\Schema\ColumnTypeMapper;

class AddColumnCommand extends Command
{
    private $column;

    /**
     * Sets a column.
     *
     * @param Column $column The column instance.
     *
     * @return AddColumnCommand
     */
    public function setColumn(Column $column)
    {
        $this->column = $column;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getSql()
    {
        if ($this->column instanceof CustomColumn) {
            $columnType = $this->column->getType();
        } else {
            $columnTypeMapper = new ColumnTypeMapper();
            $columnType = $columnTypeMapper->getNative($this->column->getType());
        }

         $sql = sprintf('ALTER TABLE %s ADD COLUMN %s %s %s %s;'
            , $this->column->getTable()->getQualifiedName()
            , $this->column->getName()
            , $columnType
            , $this->column->isNotNull() ? 'NOT NULL' : ''
            , null === $this->column->getDefault() ? '' : 'DEFAULT'. ' ' . $this->column->getDefault()
        );

        $columnDescription = $this->column->getDescription();
        if (!empty($columnDescription)) {
            $sql .= sprintf("COMMENT ON COLUMN %s.%s IS '%s';",
                $this->column->getTable()->getQualifiedName(),
                $this->column->getName(),
                $columnDescription);
        }

        return $sql;
    }

    /**
     * {@inheritdoc}
     */
    protected function postExecute()
    {
        $this->dispatcher->dispatch('column.add', new ColumnEvent($this->column, $this->getSql()));
    }
}


<?php

namespace Igorwanbarros\BaseLaravel\Toastr;

use Illuminate\Session\SessionManager as Session;
use Illuminate\Config\Repository as Config;

class Toastr
{
    /**
     * @var \Illuminate\Session\SessionManager
     */
    protected $session;

    /**
     * @var \Illuminate\Contracts\Config\Repository
     */
    protected $config;

    /**
     * @var array
     */
    protected $messages = [];

    function __construct(Session $session, Config $config)
    {
        $this->session = $session;
        $this->config  = $config;
    }

    public function message()
    {
        $messages = $this->session->get('toastr::messages');

        if (! $messages) {
            $messages = [];
        }

        $script = '<script type="text/javascript">';

        foreach ($messages as $message) {
           $config = (array) $this->config->get('toastr.options');

           if (count($message['options'])) {
               $config = array_merge($config, $message['options']);
           }

           if ($config) {
               $script .= 'toastr.options = ' . json_encode($config) . ';';
           }

           $title = $message['title'] ?: null;

            $script .= 'toastr.' . $message['type'] .
                '(\'' . $message['message'] .
                "','$title" .
                '\');';
        }

        $script .= '</script>';
        $this->session->set('toastr::messages', []);

        return $script;
    }

    /**
     * @param string $type
     * @param string $message
     * @param string $title
     * @param array  $options
     *
     * @throws \Exception
     * @return $this
     */
    public function add($type, $message, $title = null, $options = [])
    {
        $types = [
            'error',
            'info',
            'success',
            'warning',
        ];

        if (! in_array($type, $types)) {
            throw new \Exception("The $type remind message is not valid.");
        }

        $this->messages[] = [
            'type'    => $type,
            'title'   => $title,
            'message' => $message,
            'options' => $options,
        ];

        $this->session->flash('toastr::messages', $this->messages);

        return $this;
    }

    /**
     * @param string $message
     * @param string $title
     * @param array  $options
     *
     * @return $this
     */
    public function info($message, $title = null, $options = [])
    {
        return $this->add('info', $message, $title, $options);
    }

    /**
     * Add a success flash message to session.
     *
     * @param string $message
     * @param string $title
     * @param array  $options
     *
     * @return $this
     */
    public function success($message, $title = null, $options = [])
    {
        return $this->add('success', $message, $title, $options);
    }

    /**
     * @param string $message
     * @param string $title
     * @param array  $options
     *
     * @return $this
     */
    public function warning($message, $title = null, $options = [])
    {
        return $this->add('warning', $message, $title, $options);
    }

    /**
     * @param string $message
     * @param string $title
     * @param array  $options
     *
     * @return $this
     */
    public function error($message, $title = null, $options = [])
    {
        return $this->add('error', $message, $title, $options);
    }

    /**
     * @return $this
     */
    public function clear()
    {
        $this->messages = [];

        return $this;
    }
}


<?php
namespace Rentgen\Schema\Info;

use Rentgen\Schema\Command;

class SchemaExistsCommand extends Command
{
    private $schemaName;

    /**
      * Sets a schema name.
      *
      * @param string $schemaName Schema name.
      *
      * @return SchemaExistsCommand
      */
    public function setName($schemaName)
    {
        $this->schemaName = $schemaName;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getSql()
    {
        $sql = sprintf("SELECT count(schema_name) FROM information_schema.schemata WHERE schema_name = '%s';", $this->schemaName);

        return $sql;
    }

    /**
     * {@inheritdoc}
     */
    public function execute()
    {
        $this->preExecute();
        $result = $this->connection->query($this->getSql());
        foreach ($result as $row) {
            $count = $row['count'];
        }
        $this->postExecute();

        return $count > 0;
    }
}


<?php
namespace Rentgen\Schema\Info;

use Rentgen\Database\Schema;
use Rentgen\Schema\Command;

class GetSchemasCommand extends Command
{
    /**
     * {@inheritdoc}
     */
    public function getSql()
    {
        $sql = 'SELECT schema_name
                FROM information_schema.schemata
                WHERE schema_name <> \'information_schema\'
                AND schema_name !~ \'^pg_\'';

        return $sql;
    }

    /**
     * {@inheritdoc}
     */
    public function execute()
    {
        $this->preExecute();
        $result = $this->connection->query($this->getSql());
        $this->postExecute();

        $schemas = array();
        foreach ($result as $row) {
            $schemas[] = new Schema($row['schema_name']);
        }

        return $schemas;
    }
}


<?php
/**
 * Monadic Attributes
 *
 * @author    Ashley Kitson
 * @copyright Ashley Kitson, 2017, UK
 * @license   BSD-3-Clause See LICENSE.md
 */
namespace Chippyash\Attributes;

use Chippyash\Type\String\StringType;

/**
 * Trait Attribution
 *
 * Trait implementing AttributalSettable interface.
 * Declare the client class to use the AttributalSettable interface if required
 */
trait AttributionSettable
{
    /**
     * Set an attribute.  If it exists it will be replaced
     *
     * @param StringType $name Name of attribute to set
     * @param Attribute  $attribute Attribute to set
     *
     * @return Attribution
     */
    public function setA(StringType $name, Attribute $attribute)
    {
        if ($this->hasA($name)) {
            $this->attributes = $this->attributes->kDiff(
                new AttributeMap([$name() => $attribute])
            );
        }

        $this->attributes = $this->attributes->append([$name() => $attribute]);

        return $this;
    }
}


<?php
namespace Rentgen\Schema\Info;

use Rentgen\Schema\Command;
use Rentgen\Database\Table;

class TableExistsCommand extends Command
{
    private $table;

    /**
      * Sets a table.
      *
      * @param string $table A table instance.
      *
      * @return TableExistsCommand
      */
    public function setTable(Table $table)
    {
        $this->table = $table;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getSql()
    {
        $sql = sprintf(
            "SELECT count(table_name) FROM information_schema.tables WHERE table_schema = '%s' AND table_name = '%s';"
            , $this->table->getSchema()->getName()
            , $this->table->getName());

        return $sql;
    }

    /**
     * {@inheritdoc}
     */
    public function execute()
    {
        $this->preExecute();
        $result = $this->connection->query($this->getSql());
        foreach ($result as $row) {
            $count = $row['count'];
        }
        $this->postExecute();

        return (Boolean) $count;
    }
}


<?php

namespace Rentgen\Database\Constraint;

use Rentgen\Database\Table;

class PrimaryKey implements ConstraintInterface
{
    private $columns;
    private $isAutoIncrement = true;
    private $autoCreateColumn = false;
    private $table;

    /**
     * Constructor.
     *
     * @param array|string $columns Column names.
     * @param Table        $table   Table instance.
     */
    public function __construct($columns = null, Table $table = null)
    {
        $this->columns = is_string($columns) ? array($columns) : $columns;
        if (empty($this->columns)) {
            $this->autoCreateColumn = true;
        }
        $this->table = $table;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->table->getName() . '_pkey';
    }

    // TODO hmmmmmm....
    public function getColumns()
    {
        return empty($this->columns)
            ? $this->table->getName() . '_id'
            : implode(',', $this->columns);
    }

    /**
     * Return true if the primary key is auto create column.
     *
     * @return bool Auto create column
     */
    public function isAutoCreateColumn()
    {
        return $this->autoCreateColumn;
    }

    /**
     * Return true if the primary key is multi.
     *
     * @return bool Multi columns.
     */
    public function isMulti()
    {
        return count($this->columns) > 1;
    }

    /**
     * Disable auto increment.
     *
     * @return PrimaryKey Self.
     */
    public function disableAutoIncrement()
    {
        $this->isAutoIncrement = false;

        return $this;
    }

    /**
     * Return true if the primary key is auto increment.
     *
     * @return bool Auto increment.
     */
    public function isAutoIncrement()
    {
        return true === $this->isAutoIncrement;
    }

    // TODO Remove this code
    public function __toString()
    {
        return  sprintf('CONSTRAINT %s PRIMARY KEY (%s)'
            , $this->getName()
            , $this->getColumns()
        );
    }

    /**
     * {@inheritdoc}
     */
    public function getTable()
    {
        return $this->table;
    }

    /**
     * Set table instance.
     *
     * @param Table $table Table instance.
     *
     * @return PrimaryKey Self.
     */
    public function setTable(Table $table)
    {
        $this->table = $table;

        return $this;
    }
}


<?php

namespace Rentgen\Schema;

use Symfony\Component\DependencyInjection\ContainerInterface;

use Rentgen\Rentgen;
use Rentgen\Database\Column;
use Rentgen\Database\Constraint\ConstraintInterface;
use Rentgen\Database\DatabaseObjectInterface;
use Rentgen\Database\Index;
use Rentgen\Database\Schema;
use Rentgen\Database\Table;

class Manipulation
{
    private $container;

    /**
     * Constructor.
     *
     * @param Symfony\Component\DependencyInjection\ContainerInterface $container
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * Create a new database object.
     *
     * @param DatabaseObjectInterface $databaseObject Database object.
     *
     * @return integer
     */
    public function create(DatabaseObjectInterface $databaseObject)
    {
        $command = $this->getCommand($databaseObject);

        return $command->execute();
    }

    /**
     * Drop a database object.
     *
     * @param DatabaseObjectInterface $databaseObject Database object.
     * @param bool                    $cascade        Drop databse object cascade.
     *
     * @return integer
     */
    public function drop(DatabaseObjectInterface $databaseObject, $cascade = false)
    {
        $command = $this->getCommand($databaseObject, false);
        if ($cascade) {
            $command->cascade();
        }

        return $command->execute();
    }

    /**
     * Clear current database. Turn database to default state - empty public schema.
     *
     * @return integer
     */
    public function clearDatabase()
    {
        $clearDatabaseCommand = $this->container->get('rentgen.clear_database');

        return $clearDatabaseCommand->execute();
    }

    /**
     * Execute SQL query.
     *
     * @param string $sql Sql query.
     *
     * @return integer
     */
    public function execute($sql)
    {
        return $this->container
            ->get('connection')
            ->execute($sql);
    }

    /**
     * Get a command to execute.
     *
     * @param DatabaseObjectInterface $databaseObject Database object.
     * @param bool                    $cascade        Drop databse object cascade.
     *
     * @return Rentgen\Schema\Command
     */
    private function getCommand(DatabaseObjectInterface $databaseObject, $isCreate = true)
    {
        if ($databaseObject instanceof Column) {
           $command = $this->container
                ->get($isCreate ? 'rentgen.add_column' : 'rentgen.drop_column')
                ->setColumn($databaseObject);
        } elseif ($databaseObject instanceof ConstraintInterface) {
            $command = $this->container
                ->get($isCreate ? 'rentgen.add_constraint' : 'rentgen.drop_constraint')
                ->setConstraint($databaseObject);
        } elseif ($databaseObject instanceof Index) {
            $command = $this->container
                ->get($isCreate ? 'rentgen.create_index' : 'rentgen.drop_index')
                ->setIndex($databaseObject);
        } elseif ($databaseObject instanceof Schema) {
           $command = $this->container
                ->get($isCreate ? 'rentgen.create_schema' : 'rentgen.drop_schema')
                ->setSchema($databaseObject);
        } elseif ($databaseObject instanceof Table) {
            $command = $this->container
                ->get($isCreate ? 'rentgen.create_table' : 'rentgen.drop_table')
                ->setTable($databaseObject);
        } else {
            throw new \Exception(sprintf("Class %s is not supported", get_class($databaseObject)));
        }

        return $command;
    }
}


<?php
namespace Rentgen\Schema\Manipulation;

use Rentgen\Schema\Command;
use Rentgen\Schema\Info\GetSchemasCommand;

class ClearDatabaseCommand extends Command
{
    private $getSchemasCommand;

    /**
     * Constructor.
     *
     * @param GetSchemasCommand $getSchemasCommand
     */
    public function __construct(GetSchemasCommand $getSchemasCommand)
    {
        $this->getSchemasCommand = $getSchemasCommand;
    }

    /**
     * {@inheritdoc}
     */
    public function getSql()
    {
        $sql = '';
        $schemas = $this->getSchemasCommand->execute();
        foreach ($schemas as $schema) {
            $sql .= sprintf('DROP SCHEMA "%s" CASCADE;', $schema->getName());
        }
        $sql .= 'CREATE SCHEMA public;';

        return $sql;
    }
}


<?php
namespace Rentgen\Schema\Manipulation;

use Rentgen\Schema\Command;
use Rentgen\Database\Table;
use Rentgen\Event\TableEvent;

class DropTableCommand extends Command
{
    private $table;
    private $cascade = false;

    /**
     * Sets a table.
     *
     * @param Table $table The table instance.
     *
     * @return DropTableCommand
     */
    public function setTable(Table $table)
    {
        $this->table = $table;

        return $this;
    }

    /**
     * Drop table cascade.
     *
     * @return DropTableCommand
     */
    public function cascade()
    {
        $this->cascade = true;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getSql()
    {
        $sql = sprintf('DROP TABLE IF EXISTS %s%s'
            , $this->table->getQualifiedName()
            , $this->cascade ? ' CASCADE' : ''
        );
        $sql .= ';';

        return $sql;
    }

    /**
     * {@inheritdoc}
     */
    protected function preExecute()
    {
        $this->dispatcher->dispatch('table.drop', new TableEvent($this->table, $this->getSql()));
    }
}


<?php

namespace Rentgen\Schema;

use Symfony\Component\DependencyInjection\ContainerInterface;

use Rentgen\Database\Table;

class Info
{
    private $container;

     /**
     * Constructor.
     *
     * @param Symfony\Component\DependencyInjection\ContainerInterface $container
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    /**
     * Get table information.
     *
     * @param Table $table Table instance.
     *
     * @return Table Table instance.
     */
    public function getTable(Table $table)
    {
        return $this->container
            ->get('rentgen.get_table')
            ->setTableName($table->getName())
            ->execute();
    }

    /**
     * Get tables information.
     *
     * @return Table[] Array of Table instances.
     */
    public function getTables($schemaName = null)
    {
        $getTablesCommand = $this->container->get('rentgen.get_tables');
        if (null !== $schemaName) {
            $getTablesCommand->setSchemaName($schemaName);
        }

        return $getTablesCommand->execute();
    }

    /**
     * If table exists.
     *
     * @param Table $table Table instance.
     *
     * @return Boolean
     */
    public function isTableExists(Table $table)
    {
        return $this->container
            ->get('rentgen.table_exists')
            ->setTable($table)
            ->execute();
    }
}


<?php
namespace Rentgen\Schema\Info;

use Rentgen\Schema\Command;
use Rentgen\Schema\ColumnTypeMapper;
use Rentgen\Database\Table;
use Rentgen\Database\Column\ColumnCreator;
use Rentgen\Database\Constraint\ForeignKey;
use Rentgen\Database\Constraint\PrimaryKey;
use Rentgen\Database\Constraint\Unique;
use Rentgen\Exception\TableNotExistsException;

/**
 * @author Arek Jaskólski <arek.jaskolski@gmail.com>
 */
class GetTableCommand extends Command
{
    private $tableName;

    /**
     * Sets a table name.
     *
     * @param string $tableName A table name.
     *
     * @return GetTableCommand
     */
    public function setTableName($tableName)
    {
        $this->tableName = $tableName;

        return $this;
    }

    /**
     * {@inheritdoc}
     */
    public function getSql()
    {
        $sql = sprintf("SELECT table_schema, column_name, data_type, is_identity, is_nullable,
            column_default, character_maximum_length, numeric_precision, numeric_scale
            FROM information_schema.columns
            WHERE table_name ='%s';", $this->tableName);

        return $sql;
    }

    /**
     * {@inheritdoc}
     */
    public function execute()
    {
        $columnTypeMapper = new ColumnTypeMapper();

        $this->preExecute();
        $columns = $this->connection->query($this->getSql());
        if (empty($columns)) {
            throw new TableNotExistsException($this->tableName);
        }
        $table = new Table($this->tableName);
        if (null === $table->getSchema()) {
            $table->setSchema($columns[0]['table_schema']);
        }
        $columnCreator = new ColumnCreator();
        foreach ($columns as $column) {
            $columnType = $columnTypeMapper->getCommon($column['data_type']);
            $options = array();
            $options['not_null'] = $column['is_nullable'] === 'NO';
            $options['default'] = $column['column_default'];
            if ($columnType === 'string') {
                preg_match("/'(.*)'::character varying/", $column['column_default'], $matches);
                $options['default'] = isset($matches[1]) ? $matches[1] : '';
                $options['limit'] = $column['character_maximum_length'];
            }
            $column = $columnCreator->create($column['column_name'], $columnType, $options);
            $table->addColumn($column);
        }
        $this->loadConstraints($table);
        $this->postExecute();

        return $table;
    }

    /**
     * Load contsraints to table.
     *
     * @param Table $table A table.
     *
     * @return void
     */
    private function loadConstraints(Table $table)
    {

        foreach ($this->getConstraints() as $constraint) {
            switch ($constraint['constraint_type']) {
                case 'FOREIGN KEY':
                    // TODO Find a better way to define foreign key
                    $foreignKey = new ForeignKey(new Table($constraint['table_name']), new Table($constraint['column_name']));
                    $foreignKey->setColumns($constraint['references_table']);
                    $foreignKey->setReferencedColumns($constraint['references_field']);

                    $table->addConstraint($foreignKey);
                    break;
                case 'PRIMARY KEY':
                    $table->addConstraint(new PrimaryKey($constraint['column_name'], $table));
                    break;
                case 'UNIQUE':
                    $table->addConstraint(new Unique($constraint['column_name'], new Table($constraint['table_name'])));
                    break;
            }
        }
    }

    /**
     * Gets constraints from database.
     *
     * @return array Array of contraints.
     */
    private function getConstraints()
    {
        $sql = sprintf("SELECT tc.constraint_name,
            tc.constraint_type,
            tc.table_name,
            kcu.column_name,
            tc.is_deferrable,
            tc.initially_deferred,
            rc.match_option AS match_type,
            rc.update_rule AS on_update,
            rc.delete_rule AS on_delete,
            ccu.table_name AS references_table,
            ccu.column_name AS references_field
     FROM information_schema.table_constraints tc
LEFT JOIN information_schema.key_column_usage kcu
       ON tc.constraint_catalog = kcu.constraint_catalog
      AND tc.constraint_schema = kcu.constraint_schema
      AND tc.constraint_name = kcu.constraint_name
LEFT JOIN information_schema.referential_constraints rc
       ON tc.constraint_catalog = rc.constraint_catalog
      AND tc.constraint_schema = rc.constraint_schema
      AND tc.constraint_name = rc.constraint_name
LEFT JOIN information_schema.constraint_column_usage ccu
       ON rc.unique_constraint_catalog = ccu.constraint_catalog
      AND rc.unique_constraint_schema = ccu.constraint_schema
      AND rc.unique_constraint_name = ccu.constraint_name
    WHERE tc.table_name = '%s' AND tc.constraint_type IN ('PRIMARY KEY', 'FOREIGN KEY', 'UNIQUE')", $this->tableName);

        return $this->connection->query($sql);
    }
}


<?php

namespace Rentgen\Database\Constraint;

use Rentgen\Database\Table;

class ForeignKey implements ConstraintInterface
{

    const ACTION_NO_ACTION = 'NO ACTION';
    const ACTION_CASCADE   = 'CASCADE';
    const ACTION_RESTICT   = 'RESTRICT';
    const ACTION_DEFAULT   = 'SET DEFAULT';
    const ACTION_SET_NULL  = 'SET NULL';

    private $columns;
    private $table;
    private $referencedTable;
    private $updateAction;
    private $deleteAction;

    /**
     * Constructor.
     *
     * @param Table $table           Table instance.
     * @param Table $referencedTable Table reference instance.
     */
    public function __construct(Table $table, Table $referencedTable)
    {
        $this->table = $table;
        $this->referencedTable = $referencedTable;

        $this->updateAction = $this->deleteAction = self::ACTION_NO_ACTION;
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        $tableName = $this->table->getName();
        $columnsAsString = implode('_', $this->columns);

        return $tableName . '_' . $columnsAsString . '_fkey';
    }

    /**
     * {@inheritdoc}
     */
    public function getTable()
    {
        return $this->table;
    }

    /**
     * Sets a table instance.
     *
     * @param Table $table Table instance.
     *
     * @return PrimaryKey Self.
     */
    public function setTable(Table $table)
    {
        $this->table = $table;

        return $this;
    }

    /**
     * Gets a reference table name.
     *
     * @return string Reference table name.
     */
    public function getReferencedTable()
    {
        return $this->referencedTable;
    }

    /**
     * Sets foreign key columns.
     *
     * @param array $columns Columns list.
     *
     * @return ForeignKey Self instance.
     */
    public function setColumns($columns)
    {
        if (!is_array($columns)) {
            $columns = array($columns);
        }
        $this->columns = $columns;

        return $this;
    }

    /**
     * Gets column names.
     *
     * @return array Column names.
     */
    public function getColumns()
    {
        return $this->columns;
    }

    /**
     * Sets foreign key reference columns.
     *
     * @param array $columns Columns list.
     *
     * @return ForeignKey Self instance.
     */
    public function setReferencedColumns($columns)
    {
        if (!is_array($columns)) {
            $columns = array($columns);
        }
        $this->referencedColumns = $columns;

        return $this;
    }

    /**
     * Gets reference column names.
     *
     * @return array Column names.
     */
    public function getReferencedColumns()
    {
        return $this->referencedColumns;
    }

    /**
     * Gets an update action.
     *
     * @return string
     */
    public function getUpdateAction()
    {
        return $this->updateAction;
    }

    /**
     * Gets a delete action.
     *
     * @return string
     */
    public function getDeleteAction()
    {
        return $this->deleteAction;
    }

    /**
     * Sets an update action.
     *
     * @param string $updateAction Update action.
     *
     * @throws InvalidArgumentException If the provided argument is not of action type.
     *
     * @return void
     */
    public function setUpdateAction($updateAction)
    {
        $updateAction = strtoupper($updateAction);
        if (!in_array($updateAction, $this->getAvailableActions())) {
            throw new \InvalidArgumentException(sprintf('Action %s does not exist.', $updateAction));
        }
        $this->updateAction = $updateAction;
    }

    /**
     * Sets a delete action.
     *
     * @param string $deleteAction Delete action.
     *
     * @throws InvalidArgumentException If the provided argument is not of action type.
     *
     * @return void
     */
    public function setDeleteAction($deleteAction)
    {
        $deleteAction = strtoupper($deleteAction);
        if (!in_array($deleteAction, $this->getAvailableActions())) {
           throw new \InvalidArgumentException(sprintf('Action %s does not exist.', $deleteAction));
        }
        $this->deleteAction = $deleteAction;
    }

    /**
     * Sets an update action on restrict.
     *
     * @return ForeignKey
     */
    public function updateRestrict()
    {
        $this->updateAction = self::ACTION_RESTICT;

        return $this;
    }

    /**
     * Sets an update action on cascade.
     *
     * @return ForeignKey
     */
    public function updateCascade()
    {
        $this->updateAction = self::ACTION_CASCADE;

        return $this;
    }

    /**
     * Sets an update action on set null.
     *
     * @return ForeignKey
     */
    public function updateSetNull()
    {
        $this->updateAction = self::ACTION_SET_NULL;

        return $this;
    }

    /**
     * Sets an update action on default.
     *
     * @return ForeignKey
     */
    public function updateSetDefault()
    {
        $this->updateAction = self::ACTION_DEFAULT;

        return $this;
    }

    /**
     * Sets a delete action on restrict.
     *
     * @return ForeignKey
     */
    public function deleteRestrict()
    {
        $this->deleteAction = self::ACTION_RESTICT;

        return $this;
    }

    /**
     * Sets a delete action on cascade.
     *
     * @return ForeignKey
     */
    public function deleteCascade()
    {
        $this->deleteAction = self::ACTION_CASCADE;

        return $this;
    }

    /**
     * Sets a delete action on set null.
     *
     * @return ForeignKey
     */
    public function deleteSetNull()
    {
        $this->deleteAction = self::ACTION_SET_NULL;

        return $this;
    }

    /**
     * Sets a delete action on default.
     *
     * @return ForeignKey
     */
    public function deleteSetDefault()
    {
        $this->deleteAction = self::ACTION_DEFAULT;

        return $this;
    }

    private function getAvailableActions()
    {
        return array(
            ForeignKey::ACTION_NO_ACTION,
            ForeignKey::ACTION_CASCADE,
            ForeignKey::ACTION_RESTICT,
            ForeignKey::ACTION_DEFAULT,
            ForeignKey::ACTION_SET_NULL
        );
    }
}


<?php

namespace Rentgen\Database\Connection;

use Rentgen\Event\SqlEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

class Connection
{
    private $connection;
    private $config;
    private $dispatcher;

    /**
     * Constructor.
     *
     * @param ConnectionConfigInterface $config     Connection config.
     * @param EventDispatcherInterface  $dispatcher Event dispatcher.
     */
    public function __construct(ConnectionConfigInterface $config, EventDispatcherInterface $dispatcher)
    {
       $this->config = $config;
       $this->dispatcher = $dispatcher;
    }

    /**
     * Execute sql query.
     *
     * @param string $sql Sql query.
     *
     * @return integer
     */
    public function execute($sql)
    {
        $this->dispatcher->dispatch('rentgen.sql_executed', new SqlEvent($sql));

        return $this->getConnection()->exec($sql);
    }

    /**
     * Execute sql and expect return a data.
     *
     * @param string $sql Sql query.
     *
     * @return array
     */
    public function query($sql)
    {
        $rows = array();
        foreach ($this->getConnection()->query($sql) as $row) {
            $rows[] = $row;
        }

        return $rows;
    }

    private function getConnection()
    {
        if (null === $this->connection) {
            try {
                $this->connection = new \PDO($this->config->getDsn(), $this->config->getUsername(), $this->config->getPassword(),
                    array(\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION));
            } catch (\PDOException $exception) {
                throw new \InvalidArgumentException($exception->getMessage());
            }
        }

        return $this->connection;
    }
}


<?php
namespace Rentgen\Schema\Info;

use Rentgen\Schema\Command;
use Rentgen\Database\Table;
use Rentgen\Database\Schema;

class GetTablesCommand extends Command
{
    private $schemaName;

     /**
      * Sets a schema name.
      *
      * @param string $schemaName Schema name.
      *
      * @return GetTablesCommand
      */
    public function setSchemaName($schemaName)
    {
        $this->schemaName = $schemaName;

        return $this;
    }

     /**
     * {@inheritdoc}
     */
    public function getSql()
    {
        $schemaCondition = null === $this->schemaName
            ? ''
            : sprintf(" AND table_schema = '%s'", $this->schemaName);
        $sql = sprintf("SELECT table_name, table_schema FROM information_schema.tables WHERE table_schema <> 'information_schema'
            AND table_schema <> 'pg_catalog' AND table_type = 'BASE TABLE'%s;", $schemaCondition);

        return $sql;
    }

     /**
     * {@inheritdoc}
     */
    public function execute()
    {
        $this->preExecute();
        $result = $this->connection->query($this->getSql());
        $this->postExecute();

        $tables = array();
        foreach ($result as $row) {
            $tables[] = new Table($row['table_name'], new Schema($row['table_schema']));
        }

        return $tables;
    }
}