From 9e2b2a32fd0e967ad3184e9a5d091a29953acb91 Mon Sep 17 00:00:00 2001 From: Frederic Guillot Date: Wed, 25 Oct 2017 16:22:10 -0700 Subject: Include composer dependencies in repo --- vendor/fguillot/json-rpc/LICENSE | 21 + vendor/fguillot/json-rpc/src/JsonRPC/Client.php | 194 ++++++ .../JsonRPC/Exception/AccessDeniedException.php | 15 + .../Exception/AuthenticationFailureException.php | 15 + .../Exception/ConnectionFailureException.php | 15 + .../Exception/InvalidJsonFormatException.php | 15 + .../Exception/InvalidJsonRpcFormatException.php | 15 + .../Exception/ResponseEncodingFailureException.php | 15 + .../src/JsonRPC/Exception/ResponseException.php | 62 ++ .../src/JsonRPC/Exception/ServerErrorException.php | 15 + .../fguillot/json-rpc/src/JsonRPC/HttpClient.php | 365 +++++++++++ .../json-rpc/src/JsonRPC/MiddlewareHandler.php | 114 ++++ .../json-rpc/src/JsonRPC/MiddlewareInterface.php | 27 + .../json-rpc/src/JsonRPC/ProcedureHandler.php | 264 ++++++++ .../src/JsonRPC/Request/BatchRequestParser.php | 55 ++ .../src/JsonRPC/Request/RequestBuilder.php | 129 ++++ .../json-rpc/src/JsonRPC/Request/RequestParser.php | 200 ++++++ .../src/JsonRPC/Response/ResponseBuilder.php | 324 +++++++++ .../src/JsonRPC/Response/ResponseParser.php | 154 +++++ vendor/fguillot/json-rpc/src/JsonRPC/Server.php | 386 +++++++++++ .../src/JsonRPC/Validator/HostValidator.php | 30 + .../JsonRPC/Validator/JsonEncodingValidator.php | 44 ++ .../src/JsonRPC/Validator/JsonFormatValidator.php | 30 + .../src/JsonRPC/Validator/RpcFormatValidator.php | 35 + .../src/JsonRPC/Validator/UserValidator.php | 21 + vendor/fguillot/picodb/LICENSE | 21 + .../picodb/lib/PicoDb/Builder/BaseBuilder.php | 86 +++ .../picodb/lib/PicoDb/Builder/ConditionBuilder.php | 377 +++++++++++ .../picodb/lib/PicoDb/Builder/InsertBuilder.php | 36 + .../lib/PicoDb/Builder/OrConditionBuilder.php | 43 ++ .../picodb/lib/PicoDb/Builder/UpdateBuilder.php | 56 ++ vendor/fguillot/picodb/lib/PicoDb/Database.php | 370 +++++++++++ vendor/fguillot/picodb/lib/PicoDb/Driver/Base.php | 234 +++++++ vendor/fguillot/picodb/lib/PicoDb/Driver/Mssql.php | 178 +++++ vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php | 252 +++++++ .../fguillot/picodb/lib/PicoDb/Driver/Postgres.php | 196 ++++++ .../fguillot/picodb/lib/PicoDb/Driver/Sqlite.php | 193 ++++++ .../fguillot/picodb/lib/PicoDb/DriverFactory.php | 45 ++ vendor/fguillot/picodb/lib/PicoDb/Hashtable.php | 112 ++++ vendor/fguillot/picodb/lib/PicoDb/LargeObject.php | 167 +++++ vendor/fguillot/picodb/lib/PicoDb/SQLException.php | 15 + vendor/fguillot/picodb/lib/PicoDb/Schema.php | 119 ++++ .../picodb/lib/PicoDb/StatementHandler.php | 353 ++++++++++ vendor/fguillot/picodb/lib/PicoDb/Table.php | 721 +++++++++++++++++++++ vendor/fguillot/picodb/lib/PicoDb/UrlParser.php | 93 +++ vendor/fguillot/simple-queue/LICENSE | 21 + .../simple-queue/src/Adapter/AmqpQueueAdapter.php | 138 ++++ .../src/Adapter/AwsSqsQueueAdapter.php | 150 +++++ .../src/Adapter/BeanstalkQueueAdapter.php | 120 ++++ .../src/Adapter/DisqueQueueAdapter.php | 109 ++++ .../src/Adapter/MemoryQueueAdapter.php | 100 +++ .../src/Exception/NotSupportedException.php | 14 + vendor/fguillot/simple-queue/src/Job.php | 98 +++ vendor/fguillot/simple-queue/src/Queue.php | 92 +++ .../simple-queue/src/QueueAdapterInterface.php | 58 ++ vendor/fguillot/simple-validator/LICENSE | 21 + .../src/SimpleValidator/Validator.php | 44 ++ .../src/SimpleValidator/Validators/Alpha.php | 15 + .../SimpleValidator/Validators/AlphaNumeric.php | 15 + .../src/SimpleValidator/Validators/Base.php | 37 ++ .../src/SimpleValidator/Validators/Date.php | 45 ++ .../src/SimpleValidator/Validators/Email.php | 67 ++ .../src/SimpleValidator/Validators/Equals.php | 27 + .../src/SimpleValidator/Validators/Exists.php | 38 ++ .../src/SimpleValidator/Validators/GreaterThan.php | 23 + .../src/SimpleValidator/Validators/InArray.php | 23 + .../src/SimpleValidator/Validators/Integer.php | 25 + .../src/SimpleValidator/Validators/Ip.php | 15 + .../src/SimpleValidator/Validators/Length.php | 26 + .../src/SimpleValidator/Validators/MaxLength.php | 24 + .../src/SimpleValidator/Validators/MinLength.php | 24 + .../src/SimpleValidator/Validators/NotEmpty.php | 15 + .../src/SimpleValidator/Validators/NotEquals.php | 28 + .../src/SimpleValidator/Validators/NotInArray.php | 15 + .../src/SimpleValidator/Validators/Numeric.php | 15 + .../src/SimpleValidator/Validators/Range.php | 33 + .../src/SimpleValidator/Validators/Required.php | 11 + .../src/SimpleValidator/Validators/Unique.php | 48 ++ vendor/fguillot/simpleLogger/LICENSE | 21 + .../simpleLogger/src/SimpleLogger/Base.php | 89 +++ .../simpleLogger/src/SimpleLogger/File.php | 48 ++ .../simpleLogger/src/SimpleLogger/Logger.php | 94 +++ .../simpleLogger/src/SimpleLogger/Stderr.php | 25 + .../simpleLogger/src/SimpleLogger/Stdout.php | 25 + .../simpleLogger/src/SimpleLogger/Syslog.php | 72 ++ 85 files changed, 8135 insertions(+) create mode 100644 vendor/fguillot/json-rpc/LICENSE create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Client.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/AccessDeniedException.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/AuthenticationFailureException.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/ConnectionFailureException.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/InvalidJsonFormatException.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/InvalidJsonRpcFormatException.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/ResponseEncodingFailureException.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/ResponseException.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/HttpClient.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/ProcedureHandler.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseBuilder.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Server.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Validator/HostValidator.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Validator/JsonEncodingValidator.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Validator/JsonFormatValidator.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Validator/RpcFormatValidator.php create mode 100644 vendor/fguillot/json-rpc/src/JsonRPC/Validator/UserValidator.php create mode 100644 vendor/fguillot/picodb/LICENSE create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Builder/BaseBuilder.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Builder/ConditionBuilder.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Builder/InsertBuilder.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Builder/OrConditionBuilder.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Builder/UpdateBuilder.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Database.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Driver/Base.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Driver/Mssql.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/DriverFactory.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Hashtable.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/LargeObject.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/SQLException.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Schema.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/StatementHandler.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/Table.php create mode 100644 vendor/fguillot/picodb/lib/PicoDb/UrlParser.php create mode 100644 vendor/fguillot/simple-queue/LICENSE create mode 100644 vendor/fguillot/simple-queue/src/Adapter/AmqpQueueAdapter.php create mode 100644 vendor/fguillot/simple-queue/src/Adapter/AwsSqsQueueAdapter.php create mode 100644 vendor/fguillot/simple-queue/src/Adapter/BeanstalkQueueAdapter.php create mode 100644 vendor/fguillot/simple-queue/src/Adapter/DisqueQueueAdapter.php create mode 100644 vendor/fguillot/simple-queue/src/Adapter/MemoryQueueAdapter.php create mode 100644 vendor/fguillot/simple-queue/src/Exception/NotSupportedException.php create mode 100644 vendor/fguillot/simple-queue/src/Job.php create mode 100644 vendor/fguillot/simple-queue/src/Queue.php create mode 100644 vendor/fguillot/simple-queue/src/QueueAdapterInterface.php create mode 100644 vendor/fguillot/simple-validator/LICENSE create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validator.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Alpha.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/AlphaNumeric.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Base.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Ip.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Length.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEmpty.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php create mode 100644 vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php create mode 100644 vendor/fguillot/simpleLogger/LICENSE create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/Base.php create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/File.php create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/Logger.php create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/Stderr.php create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/Stdout.php create mode 100644 vendor/fguillot/simpleLogger/src/SimpleLogger/Syslog.php (limited to 'vendor/fguillot') diff --git a/vendor/fguillot/json-rpc/LICENSE b/vendor/fguillot/json-rpc/LICENSE new file mode 100644 index 00000000..6a362bc1 --- /dev/null +++ b/vendor/fguillot/json-rpc/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Frederic Guillot + +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. diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Client.php b/vendor/fguillot/json-rpc/src/JsonRPC/Client.php new file mode 100644 index 00000000..fed1ce30 --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Client.php @@ -0,0 +1,194 @@ +httpClient = $httpClient ?: new HttpClient($url); + $this->returnException = $returnException; + } + + /** + * Arguments passed are always positional + * + * @access public + * @return $this + */ + public function withPositionalArguments() + { + $this->isNamedArguments = false; + return $this; + } + + /** + * Get HTTP Client + * + * @access public + * @return HttpClient + */ + public function getHttpClient() + { + return $this->httpClient; + } + + /** + * Set username and password + * + * @access public + * @param string $username + * @param string $password + * @return $this + */ + public function authentication($username, $password) + { + $this->httpClient + ->withUsername($username) + ->withPassword($password); + + return $this; + } + + /** + * Automatic mapping of procedures + * + * @access public + * @param string $method Procedure name + * @param array $params Procedure arguments + * @return mixed + */ + public function __call($method, array $params) + { + if ($this->isNamedArguments && count($params) === 1 && is_array($params[0])) { + $params = $params[0]; + } + + return $this->execute($method, $params); + } + + /** + * Start a batch request + * + * @access public + * @return Client + */ + public function batch() + { + $this->isBatch = true; + $this->batch = array(); + return $this; + } + + /** + * Send a batch request + * + * @access public + * @return array + */ + public function send() + { + $this->isBatch = false; + return $this->sendPayload('['.implode(', ', $this->batch).']'); + } + + /** + * Execute a procedure + * + * @access public + * @param string $procedure Procedure name + * @param array $params Procedure arguments + * @param array $reqattrs + * @return mixed + */ + public function execute($procedure, array $params = array(), array $reqattrs = array()) + { + $payload = RequestBuilder::create() + ->withProcedure($procedure) + ->withParams($params) + ->withRequestAttributes($reqattrs) + ->build(); + + if ($this->isBatch) { + $this->batch[] = $payload; + return $this; + } + + return $this->sendPayload($payload); + } + + /** + * Send payload + * + * @access private + * @throws Exception + * @param string $payload + * @return Exception|Client + */ + private function sendPayload($payload) + { + return ResponseParser::create() + ->withReturnException($this->returnException) + ->withPayload($this->httpClient->execute($payload)) + ->parse(); + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Exception/AccessDeniedException.php b/vendor/fguillot/json-rpc/src/JsonRPC/Exception/AccessDeniedException.php new file mode 100644 index 00000000..8cb9bc2b --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Exception/AccessDeniedException.php @@ -0,0 +1,15 @@ +setData($data); + } + + /** + * Attach additional information + * + * @access public + * @param mixed $data [optional] A value that contains additional information about the error. + * @return \JsonRPC\Exception\ResponseException + */ + public function setData($data = null) + { + $this->data = $data; + return $this; + } + + /** + * Get additional information + * + * @access public + * @return mixed|null + */ + public function getData() + { + return $this->data; + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php b/vendor/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php new file mode 100644 index 00000000..ab3ea584 --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Exception/ServerErrorException.php @@ -0,0 +1,15 @@ +', + 'Content-Type: application/json', + 'Accept: application/json', + 'Connection: close', + ); + + /** + * Username for authentication + * + * @access private + * @var string + */ + private $username; + + /** + * Password for authentication + * + * @access private + * @var string + */ + private $password; + + /** + * Enable debug output to the php error log + * + * @access private + * @var boolean + */ + private $debug = false; + + /** + * Cookies + * + * @access private + * @var array + */ + private $cookies = array(); + + /** + * SSL certificates verification + * + * @access private + * @var boolean + */ + private $verifySslCertificate = true; + + /** + * Callback called before the doing the request + * + * @access private + * @var Closure + */ + private $beforeRequest; + + /** + * HttpClient constructor + * + * @access public + * @param string $url + */ + public function __construct($url = '') + { + $this->url = $url; + } + + /** + * Set URL + * + * @access public + * @param string $url + * @return $this + */ + public function withUrl($url) + { + $this->url = $url; + return $this; + } + + /** + * Set username + * + * @access public + * @param string $username + * @return $this + */ + public function withUsername($username) + { + $this->username = $username; + return $this; + } + + /** + * Set password + * + * @access public + * @param string $password + * @return $this + */ + public function withPassword($password) + { + $this->password = $password; + return $this; + } + + /** + * Set timeout + * + * @access public + * @param integer $timeout + * @return $this + */ + public function withTimeout($timeout) + { + $this->timeout = $timeout; + return $this; + } + + /** + * Set timeout + * + * @access public + * @param array $headers + * @return $this + */ + public function withHeaders(array $headers) + { + $this->headers = array_merge($this->headers, $headers); + return $this; + } + + /** + * Set cookies + * + * @access public + * @param array $cookies + * @param boolean $replace + */ + public function withCookies(array $cookies, $replace = false) + { + if ($replace) { + $this->cookies = $cookies; + } else { + $this->cookies = array_merge($this->cookies, $cookies); + } + } + + /** + * Enable debug mode + * + * @access public + * @return $this + */ + public function withDebug() + { + $this->debug = true; + return $this; + } + + /** + * Disable SSL verification + * + * @access public + * @return $this + */ + public function withoutSslVerification() + { + $this->verifySslCertificate = false; + return $this; + } + + /** + * Assign a callback before the request + * + * @access public + * @param Closure $closure + * @return $this + */ + public function withBeforeRequestCallback(Closure $closure) + { + $this->beforeRequest = $closure; + return $this; + } + + /** + * Get cookies + * + * @access public + * @return array + */ + public function getCookies() + { + return $this->cookies; + } + + /** + * Do the HTTP request + * + * @access public + * @throws ConnectionFailureException + * @param string $payload + * @return array + */ + public function execute($payload) + { + if (is_callable($this->beforeRequest)) { + call_user_func_array($this->beforeRequest, array($this, $payload)); + } + + $stream = fopen(trim($this->url), 'r', false, $this->buildContext($payload)); + + if (! is_resource($stream)) { + throw new ConnectionFailureException('Unable to establish a connection'); + } + + $metadata = stream_get_meta_data($stream); + $headers = $metadata['wrapper_data']; + $response = json_decode(stream_get_contents($stream), true); + + if ($this->debug) { + error_log('==> Request: '.PHP_EOL.(is_string($payload) ? $payload : json_encode($payload, JSON_PRETTY_PRINT))); + error_log('==> Headers: '.PHP_EOL.var_export($headers, true)); + error_log('==> Response: '.PHP_EOL.json_encode($response, JSON_PRETTY_PRINT)); + } + + $this->handleExceptions($headers); + $this->parseCookies($headers); + + return $response; + } + + /** + * Prepare stream context + * + * @access private + * @param string $payload + * @return resource + */ + private function buildContext($payload) + { + $headers = $this->headers; + + if (! empty($this->username) && ! empty($this->password)) { + $headers[] = 'Authorization: Basic '.base64_encode($this->username.':'.$this->password); + } + + if (! empty($this->cookies)){ + $cookies = array(); + + foreach ($this->cookies as $key => $value) { + $cookies[] = $key.'='.$value; + } + + $headers[] = 'Cookie: '.implode('; ', $cookies); + } + + return stream_context_create(array( + 'http' => array( + 'method' => 'POST', + 'protocol_version' => 1.1, + 'timeout' => $this->timeout, + 'max_redirects' => 2, + 'header' => implode("\r\n", $headers), + 'content' => $payload, + 'ignore_errors' => true, + ), + 'ssl' => array( + 'verify_peer' => $this->verifySslCertificate, + 'verify_peer_name' => $this->verifySslCertificate, + ) + )); + } + + /** + * Parse cookies from response + * + * @access private + * @param array $headers + */ + private function parseCookies(array $headers) + { + foreach ($headers as $header) { + $pos = stripos($header, 'Set-Cookie:'); + + if ($pos !== false) { + $cookies = explode(';', substr($header, $pos + 11)); + + foreach ($cookies as $cookie) { + $item = explode('=', $cookie); + + if (count($item) === 2) { + $name = trim($item[0]); + $value = $item[1]; + $this->cookies[$name] = $value; + } + } + } + } + } + + /** + * Throw an exception according the HTTP response + * + * @access public + * @param array $headers + * @throws AccessDeniedException + * @throws ServerErrorException + */ + public function handleExceptions(array $headers) + { + $exceptions = array( + '401' => '\JsonRPC\Exception\AccessDeniedException', + '403' => '\JsonRPC\Exception\AccessDeniedException', + '404' => '\JsonRPC\Exception\ConnectionFailureException', + '500' => '\JsonRPC\Exception\ServerErrorException', + ); + + foreach ($headers as $header) { + foreach ($exceptions as $code => $exception) { + if (strpos($header, 'HTTP/1.0 '.$code) !== false || strpos($header, 'HTTP/1.1 '.$code) !== false) { + throw new $exception('Response: '.$header); + } + } + } + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php new file mode 100644 index 00000000..61d5a2d2 --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareHandler.php @@ -0,0 +1,114 @@ +username = $username; + } + + return $this; + } + + /** + * Set password + * + * @access public + * @param string $password + * @return $this + */ + public function withPassword($password) + { + if (! empty($password)) { + $this->password = $password; + } + + return $this; + } + + /** + * Set procedure name + * + * @access public + * @param string $procedureName + * @return $this + */ + public function withProcedure($procedureName) + { + $this->procedureName = $procedureName; + return $this; + } + + /** + * Add a new middleware + * + * @access public + * @param MiddlewareInterface $middleware + * @return MiddlewareHandler + */ + public function withMiddleware(MiddlewareInterface $middleware) + { + $this->middleware[] = $middleware; + return $this; + } + + /** + * Execute all middleware + * + * @access public + */ + public function execute() + { + foreach ($this->middleware as $middleware) { + $middleware->execute($this->username, $this->password, $this->procedureName); + } + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php new file mode 100644 index 00000000..ab55261d --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/MiddlewareInterface.php @@ -0,0 +1,27 @@ +callbacks[$procedure] = $callback; + return $this; + } + + /** + * Bind a procedure to a class + * + * @access public + * @param string $procedure Procedure name + * @param mixed $class Class name or instance + * @param string $method Procedure name + * @return $this + */ + public function withClassAndMethod($procedure, $class, $method = '') + { + if ($method === '') { + $method = $procedure; + } + + $this->classes[$procedure] = array($class, $method); + return $this; + } + + /** + * Bind a class instance + * + * @access public + * @param mixed $instance + * @return $this + */ + public function withObject($instance) + { + $this->instances[] = $instance; + return $this; + } + + /** + * Set a before method to call + * + * @access public + * @param string $methodName + * @return $this + */ + public function withBeforeMethod($methodName) + { + $this->beforeMethodName = $methodName; + return $this; + } + + /** + * Execute the procedure + * + * @access public + * @param string $procedure Procedure name + * @param array $params Procedure params + * @return mixed + */ + public function executeProcedure($procedure, array $params = array()) + { + if (isset($this->callbacks[$procedure])) { + return $this->executeCallback($this->callbacks[$procedure], $params); + } elseif (isset($this->classes[$procedure]) && method_exists($this->classes[$procedure][0], $this->classes[$procedure][1])) { + return $this->executeMethod($this->classes[$procedure][0], $this->classes[$procedure][1], $params); + } + + foreach ($this->instances as $instance) { + if (method_exists($instance, $procedure)) { + return $this->executeMethod($instance, $procedure, $params); + } + } + + throw new BadFunctionCallException('Unable to find the procedure'); + } + + /** + * Execute a callback + * + * @access public + * @param Closure $callback Callback + * @param array $params Procedure params + * @return mixed + */ + public function executeCallback(Closure $callback, $params) + { + $reflection = new ReflectionFunction($callback); + + $arguments = $this->getArguments( + $params, + $reflection->getParameters(), + $reflection->getNumberOfRequiredParameters(), + $reflection->getNumberOfParameters() + ); + + return $reflection->invokeArgs($arguments); + } + + /** + * Execute a method + * + * @access public + * @param mixed $class Class name or instance + * @param string $method Method name + * @param array $params Procedure params + * @return mixed + */ + public function executeMethod($class, $method, $params) + { + $instance = is_string($class) ? new $class : $class; + $reflection = new ReflectionMethod($class, $method); + + $this->executeBeforeMethod($instance, $method); + + $arguments = $this->getArguments( + $params, + $reflection->getParameters(), + $reflection->getNumberOfRequiredParameters(), + $reflection->getNumberOfParameters() + ); + + return $reflection->invokeArgs($instance, $arguments); + } + + /** + * Execute before method if defined + * + * @access public + * @param mixed $object + * @param string $method + */ + public function executeBeforeMethod($object, $method) + { + if ($this->beforeMethodName !== '' && method_exists($object, $this->beforeMethodName)) { + call_user_func_array(array($object, $this->beforeMethodName), array($method)); + } + } + + /** + * Get procedure arguments + * + * @access public + * @param array $requestParams Incoming arguments + * @param array $methodParams Procedure arguments + * @param integer $nbRequiredParams Number of required parameters + * @param integer $nbMaxParams Maximum number of parameters + * @return array + */ + public function getArguments(array $requestParams, array $methodParams, $nbRequiredParams, $nbMaxParams) + { + $nbParams = count($requestParams); + + if ($nbParams < $nbRequiredParams) { + throw new InvalidArgumentException('Wrong number of arguments'); + } + + if ($nbParams > $nbMaxParams) { + throw new InvalidArgumentException('Too many arguments'); + } + + if ($this->isPositionalArguments($requestParams)) { + return $requestParams; + } + + return $this->getNamedArguments($requestParams, $methodParams); + } + + /** + * Return true if we have positional parameters + * + * @access public + * @param array $request_params Incoming arguments + * @return bool + */ + public function isPositionalArguments(array $request_params) + { + return array_keys($request_params) === range(0, count($request_params) - 1); + } + + /** + * Get named arguments + * + * @access public + * @param array $requestParams Incoming arguments + * @param array $methodParams Procedure arguments + * @return array + */ + public function getNamedArguments(array $requestParams, array $methodParams) + { + $params = array(); + + foreach ($methodParams as $p) { + $name = $p->getName(); + + if (isset($requestParams[$name])) { + $params[$name] = $requestParams[$name]; + } elseif ($p->isDefaultValueAvailable()) { + $params[$name] = $p->getDefaultValue(); + } else { + throw new InvalidArgumentException('Missing argument: '.$name); + } + } + + return $params; + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php b/vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php new file mode 100644 index 00000000..c0fc776e --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Request/BatchRequestParser.php @@ -0,0 +1,55 @@ +payload as $payload) { + $responses[] = RequestParser::create() + ->withPayload($payload) + ->withProcedureHandler($this->procedureHandler) + ->withMiddlewareHandler($this->middlewareHandler) + ->withLocalException($this->localExceptions) + ->parse(); + } + + $responses = array_filter($responses); + return empty($responses) ? '' : '['.implode(',', $responses).']'; + } + + /** + * Return true if we have a batch request + * + * ex : [ + * 0 => '...', + * 1 => '...', + * 2 => '...', + * 3 => '...', + * ] + * + * @static + * @access public + * @param array $payload + * @return bool + */ + public static function isBatchRequest(array $payload) + { + return array_keys($payload) === range(0, count($payload) - 1); + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php new file mode 100644 index 00000000..145d21c1 --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestBuilder.php @@ -0,0 +1,129 @@ +id = $id; + return $this; + } + + /** + * Set method + * + * @access public + * @param string $procedure + * @return RequestBuilder + */ + public function withProcedure($procedure) + { + $this->procedure = $procedure; + return $this; + } + + /** + * Set parameters + * + * @access public + * @param array $params + * @return RequestBuilder + */ + public function withParams(array $params) + { + $this->params = $params; + return $this; + } + + /** + * Set additional request attributes + * + * @access public + * @param array $reqattrs + * @return RequestBuilder + */ + public function withRequestAttributes(array $reqattrs) + { + $this->reqattrs = $reqattrs; + return $this; + } + + /** + * Build the payload + * + * @access public + * @return string + */ + public function build() + { + $payload = array_merge_recursive($this->reqattrs, array( + 'jsonrpc' => '2.0', + 'method' => $this->procedure, + 'id' => $this->id ?: mt_rand(), + )); + + if (! empty($this->params)) { + $payload['params'] = $this->params; + } + + return json_encode($payload); + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php new file mode 100644 index 00000000..ea1b7d43 --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Request/RequestParser.php @@ -0,0 +1,200 @@ +payload = $payload; + return $this; + } + + /** + * Exception classes that should not be relayed to the client + * + * @access public + * @param mixed $exception + * @return $this + */ + public function withLocalException($exception) + { + if (is_array($exception)) { + $this->localExceptions = array_merge($this->localExceptions, $exception); + } else { + $this->localExceptions[] = $exception; + } + + return $this; + } + + /** + * Set procedure handler + * + * @access public + * @param ProcedureHandler $procedureHandler + * @return $this + */ + public function withProcedureHandler(ProcedureHandler $procedureHandler) + { + $this->procedureHandler = $procedureHandler; + return $this; + } + + /** + * Set middleware handler + * + * @access public + * @param MiddlewareHandler $middlewareHandler + * @return $this + */ + public function withMiddlewareHandler(MiddlewareHandler $middlewareHandler) + { + $this->middlewareHandler = $middlewareHandler; + return $this; + } + + /** + * Parse incoming request + * + * @access public + * @return string + * @throws AccessDeniedException + * @throws AuthenticationFailureException + */ + public function parse() + { + try { + + JsonFormatValidator::validate($this->payload); + RpcFormatValidator::validate($this->payload); + + $this->middlewareHandler + ->withProcedure($this->payload['method']) + ->execute(); + + $result = $this->procedureHandler->executeProcedure( + $this->payload['method'], + empty($this->payload['params']) ? array() : $this->payload['params'] + ); + + if (! $this->isNotification()) { + return ResponseBuilder::create() + ->withId($this->payload['id']) + ->withResult($result) + ->build(); + } + } catch (Exception $e) { + return $this->handleExceptions($e); + } + + return ''; + } + + /** + * Handle exceptions + * + * @access protected + * @param Exception $e + * @return string + * @throws Exception + */ + protected function handleExceptions(Exception $e) + { + foreach ($this->localExceptions as $exception) { + if ($e instanceof $exception) { + throw $e; + } + } + + if ($e instanceof InvalidJsonRpcFormatException || ! $this->isNotification()) { + return ResponseBuilder::create() + ->withId(isset($this->payload['id']) ? $this->payload['id'] : null) + ->withException($e) + ->build(); + } + + return ''; + } + + /** + * Return true if the message is a notification + * + * @access protected + * @return bool + */ + protected function isNotification() + { + return is_array($this->payload) && !isset($this->payload['id']); + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseBuilder.php b/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseBuilder.php new file mode 100644 index 00000000..c1caff92 --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseBuilder.php @@ -0,0 +1,324 @@ + 'application/json', + ); + + /** + * HTTP status + * + * @access private + * @var string + */ + private $status; + + /** + * Exception + * + * @access private + * @var ResponseException + */ + private $exception; + + /** + * Get new object instance + * + * @static + * @access public + * @return ResponseBuilder + */ + public static function create() + { + return new static(); + } + + /** + * Set id + * + * @access public + * @param mixed $id + * @return $this + */ + public function withId($id) + { + $this->id = $id; + return $this; + } + + /** + * Set result + * + * @access public + * @param mixed $result + * @return $this + */ + public function withResult($result) + { + $this->result = $result; + return $this; + } + + /** + * Set error + * + * @access public + * @param integer $code + * @param string $message + * @param string $data + * @return $this + */ + public function withError($code, $message, $data = '') + { + $this->errorCode = $code; + $this->errorMessage = $message; + $this->errorData = $data; + return $this; + } + + /** + * Set exception + * + * @access public + * @param Exception $exception + * @return $this + */ + public function withException(Exception $exception) + { + $this->exception = $exception; + return $this; + } + + /** + * Add HTTP header + * + * @access public + * @param string $name + * @param string $value + * @return $this + */ + public function withHeader($name, $value) + { + $this->headers[$name] = $value; + return $this; + } + + /** + * Add HTTP Status + * + * @access public + * @param string $status + * @return $this + */ + public function withStatus($status) + { + $this->status = $status; + return $this; + } + + /** + * Get status + * + * @access public + * @return string + */ + public function getStatus() + { + return $this->status; + } + + /** + * Get headers + * + * @access public + * @return string[] + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * Build response + * + * @access public + * @return string + */ + public function build() + { + $encodedResponse = json_encode($this->buildResponse()); + JsonEncodingValidator::validate(); + + return $encodedResponse; + } + + /** + * Send HTTP headers + * + * @access public + * @return $this + */ + public function sendHeaders() + { + if (! empty($this->status)) { + header($this->status); + } + + foreach ($this->headers as $name => $value) { + header($name.': '.$value); + } + + return $this; + } + + /** + * Build response payload + * + * @access private + * @return array + */ + private function buildResponse() + { + $response = array('jsonrpc' => '2.0'); + $this->handleExceptions(); + + if (! empty($this->errorMessage)) { + $response['error'] = $this->buildErrorResponse(); + } else { + $response['result'] = $this->result; + } + + $response['id'] = $this->id; + return $response; + } + + /** + * Build response error payload + * + * @access private + * @return array + */ + private function buildErrorResponse() + { + $response = array( + 'code' => $this->errorCode, + 'message' => $this->errorMessage, + ); + + if (! empty($this->errorData)) { + $response['data'] = $this->errorData; + } + + return $response; + } + + /** + * Transform exceptions to JSON-RPC errors + * + * @access private + */ + private function handleExceptions() + { + if ($this->exception instanceof InvalidJsonFormatException) { + $this->errorCode = -32700; + $this->errorMessage = 'Parse error'; + $this->id = null; + } elseif ($this->exception instanceof InvalidJsonRpcFormatException) { + $this->errorCode = -32600; + $this->errorMessage = 'Invalid Request'; + $this->id = null; + } elseif ($this->exception instanceof BadFunctionCallException) { + $this->errorCode = -32601; + $this->errorMessage = 'Method not found'; + } elseif ($this->exception instanceof InvalidArgumentException) { + $this->errorCode = -32602; + $this->errorMessage = 'Invalid params'; + } elseif ($this->exception instanceof ResponseEncodingFailureException) { + $this->errorCode = -32603; + $this->errorMessage = 'Internal error'; + $this->errorData = $this->exception->getMessage(); + } elseif ($this->exception instanceof AuthenticationFailureException) { + $this->errorCode = 401; + $this->errorMessage = 'Unauthorized'; + $this->status = 'HTTP/1.0 401 Unauthorized'; + $this->withHeader('WWW-Authenticate', 'Basic realm="JsonRPC"'); + } elseif ($this->exception instanceof AccessDeniedException) { + $this->errorCode = 403; + $this->errorMessage = 'Forbidden'; + $this->status = 'HTTP/1.0 403 Forbidden'; + } elseif ($this->exception instanceof ResponseException) { + $this->errorCode = $this->exception->getCode(); + $this->errorMessage = $this->exception->getMessage(); + $this->errorData = $this->exception->getData(); + } elseif ($this->exception instanceof Exception) { + $this->errorCode = $this->exception->getCode(); + $this->errorMessage = $this->exception->getMessage(); + } + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php b/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php new file mode 100644 index 00000000..02d449ba --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Response/ResponseParser.php @@ -0,0 +1,154 @@ +returnException = $returnException; + return $this; + } + + /** + * Set payload + * + * @access public + * @param mixed $payload + * @return $this + */ + public function withPayload($payload) + { + $this->payload = $payload; + return $this; + } + + /** + * Parse response + * + * @return array|Exception|null + * @throws InvalidJsonFormatException + * @throws BadFunctionCallException + * @throws InvalidJsonRpcFormatException + * @throws InvalidArgumentException + * @throws Exception + * @throws ResponseException + */ + public function parse() + { + JsonFormatValidator::validate($this->payload); + + if ($this->isBatchResponse()) { + $results = array(); + + foreach ($this->payload as $response) { + $results[] = self::create() + ->withReturnException($this->returnException) + ->withPayload($response) + ->parse(); + } + + return $results; + } + + if (isset($this->payload['error']['code'])) { + try { + $this->handleExceptions(); + } catch (Exception $e) { + if ($this->returnException) { + return $e; + } + throw $e; + } + } + + return isset($this->payload['result']) ? $this->payload['result'] : null; + } + + /** + * Handle exceptions + * + * @access private + * @throws InvalidJsonFormatException + * @throws InvalidJsonRpcFormatException + * @throws ResponseException + */ + private function handleExceptions() + { + switch ($this->payload['error']['code']) { + case -32700: + throw new InvalidJsonFormatException('Parse error: '.$this->payload['error']['message']); + case -32600: + throw new InvalidJsonRpcFormatException('Invalid Request: '.$this->payload['error']['message']); + case -32601: + throw new BadFunctionCallException('Procedure not found: '.$this->payload['error']['message']); + case -32602: + throw new InvalidArgumentException('Invalid arguments: '.$this->payload['error']['message']); + default: + throw new ResponseException( + $this->payload['error']['message'], + $this->payload['error']['code'], + null, + isset($this->payload['error']['data']) ? $this->payload['error']['data'] : null + ); + } + } + + /** + * Return true if we have a batch response + * + * @access private + * @return boolean + */ + private function isBatchResponse() + { + return array_keys($this->payload) === range(0, count($this->payload) - 1); + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Server.php b/vendor/fguillot/json-rpc/src/JsonRPC/Server.php new file mode 100644 index 00000000..1ed075a4 --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Server.php @@ -0,0 +1,386 @@ +payload = json_decode($request, true); + } else { + $this->payload = json_decode(file_get_contents('php://input'), true); + } + + $this->serverVariable = $server ?: $_SERVER; + $this->responseBuilder = $responseBuilder ?: ResponseBuilder::create(); + $this->requestParser = $requestParser ?: RequestParser::create(); + $this->batchRequestParser = $batchRequestParser ?: BatchRequestParser::create(); + $this->procedureHandler = $procedureHandler ?: new ProcedureHandler(); + $this->middlewareHandler = $middlewareHandler ?: new MiddlewareHandler(); + } + + /** + * Define alternative authentication header + * + * @access public + * @param string $header Header name + * @return $this + */ + public function setAuthenticationHeader($header) + { + if (! empty($header)) { + $header = 'HTTP_'.str_replace('-', '_', strtoupper($header)); + $value = $this->getServerVariable($header); + + if (! empty($value)) { + list($this->username, $this->password) = explode(':', base64_decode($value)); + } + } + + return $this; + } + + /** + * Get ProcedureHandler + * + * @access public + * @return ProcedureHandler + */ + public function getProcedureHandler() + { + return $this->procedureHandler; + } + + /** + * Get MiddlewareHandler + * + * @access public + * @return MiddlewareHandler + */ + public function getMiddlewareHandler() + { + return $this->middlewareHandler; + } + + /** + * Get username + * + * @access public + * @return string + */ + public function getUsername() + { + return $this->username ?: $this->getServerVariable('PHP_AUTH_USER'); + } + + /** + * Get password + * + * @access public + * @return string + */ + public function getPassword() + { + return $this->password ?: $this->getServerVariable('PHP_AUTH_PW'); + } + + /** + * IP based client restrictions + * + * @access public + * @param array $hosts List of hosts + * @return $this + */ + public function allowHosts(array $hosts) + { + $this->hosts = $hosts; + return $this; + } + + /** + * HTTP Basic authentication + * + * @access public + * @param array $users Dictionary of username/password + * @return $this + */ + public function authentication(array $users) + { + $this->users = $users; + return $this; + } + + /** + * Register a new procedure + * + * @access public + * @deprecated Use $server->getProcedureHandler()->withCallback($procedure, $callback) + * @param string $procedure Procedure name + * @param closure $callback Callback + * @return $this + */ + public function register($procedure, Closure $callback) + { + $this->procedureHandler->withCallback($procedure, $callback); + return $this; + } + + /** + * Bind a procedure to a class + * + * @access public + * @deprecated Use $server->getProcedureHandler()->withClassAndMethod($procedure, $class, $method); + * @param string $procedure Procedure name + * @param mixed $class Class name or instance + * @param string $method Procedure name + * @return $this + */ + public function bind($procedure, $class, $method = '') + { + $this->procedureHandler->withClassAndMethod($procedure, $class, $method); + return $this; + } + + /** + * Bind a class instance + * + * @access public + * @deprecated Use $server->getProcedureHandler()->withObject($instance); + * @param mixed $instance Instance name + * @return $this + */ + public function attach($instance) + { + $this->procedureHandler->withObject($instance); + return $this; + } + + /** + * Exception classes that should not be relayed to the client + * + * @access public + * @param Exception|string $exception + * @return $this + */ + public function withLocalException($exception) + { + $this->localExceptions[] = $exception; + return $this; + } + + /** + * Parse incoming requests + * + * @access public + * @return string + */ + public function execute() + { + try { + JsonFormatValidator::validate($this->payload); + HostValidator::validate($this->hosts, $this->getServerVariable('REMOTE_ADDR')); + UserValidator::validate($this->users, $this->getUsername(), $this->getPassword()); + + $this->middlewareHandler + ->withUsername($this->getUsername()) + ->withPassword($this->getPassword()) + ; + + $response = $this->parseRequest(); + + } catch (Exception $e) { + $response = $this->handleExceptions($e); + } + + $this->responseBuilder->sendHeaders(); + return $response; + } + + /** + * Handle exceptions + * + * @access protected + * @param Exception $e + * @return string + * @throws Exception + */ + protected function handleExceptions(Exception $e) + { + foreach ($this->localExceptions as $exception) { + if ($e instanceof $exception) { + throw $e; + } + } + + return $this->responseBuilder->withException($e)->build(); + } + + /** + * Parse incoming request + * + * @access protected + * @return string + */ + protected function parseRequest() + { + if (BatchRequestParser::isBatchRequest($this->payload)) { + return $this->batchRequestParser + ->withPayload($this->payload) + ->withProcedureHandler($this->procedureHandler) + ->withMiddlewareHandler($this->middlewareHandler) + ->withLocalException($this->localExceptions) + ->parse(); + } + + return $this->requestParser + ->withPayload($this->payload) + ->withProcedureHandler($this->procedureHandler) + ->withMiddlewareHandler($this->middlewareHandler) + ->withLocalException($this->localExceptions) + ->parse(); + } + + /** + * Check existence and get value of server variable + * + * @access protected + * @param string $variable + * @return string|null + */ + protected function getServerVariable($variable) + { + return isset($this->serverVariable[$variable]) ? $this->serverVariable[$variable] : null; + } +} diff --git a/vendor/fguillot/json-rpc/src/JsonRPC/Validator/HostValidator.php b/vendor/fguillot/json-rpc/src/JsonRPC/Validator/HostValidator.php new file mode 100644 index 00000000..7f8c0a04 --- /dev/null +++ b/vendor/fguillot/json-rpc/src/JsonRPC/Validator/HostValidator.php @@ -0,0 +1,30 @@ +db = $db; + $this->conditionBuilder = $condition; + } + + /** + * Get object instance + * + * @static + * @access public + * @param Database $db + * @param ConditionBuilder $condition + * @return static + */ + public static function getInstance(Database $db, ConditionBuilder $condition) + { + return new static($db, $condition); + } + + /** + * Set table name + * + * @access public + * @param string $table + * @return $this + */ + public function withTable($table) + { + $this->table = $table; + return $this; + } + + /** + * Set columns name + * + * @access public + * @param string[] $columns + * @return $this + */ + public function withColumns(array $columns) + { + $this->columns = $columns; + return $this; + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Builder/ConditionBuilder.php b/vendor/fguillot/picodb/lib/PicoDb/Builder/ConditionBuilder.php new file mode 100644 index 00000000..b0465b6e --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Builder/ConditionBuilder.php @@ -0,0 +1,377 @@ +db = $db; + } + + /** + * Build the SQL condition + * + * @access public + * @return string + */ + public function build() + { + return empty($this->conditions) ? '' : ' WHERE '.implode(' AND ', $this->conditions); + } + + /** + * Get condition values + * + * @access public + * @return array + */ + public function getValues() + { + return $this->values; + } + + /** + * Returns true if there is some conditions + * + * @access public + * @return boolean + */ + public function hasCondition() + { + return ! empty($this->conditions); + } + + /** + * Add custom condition + * + * @access public + * @param string $sql + */ + public function addCondition($sql) + { + if ($this->orConditionOffset > 0) { + $this->orConditions[$this->orConditionOffset]->withCondition($sql); + } + else { + $this->conditions[] = $sql; + } + } + + /** + * Start OR condition + * + * @access public + */ + public function beginOr() + { + $this->orConditionOffset++; + $this->orConditions[$this->orConditionOffset] = new OrConditionBuilder(); + } + + /** + * Close OR condition + * + * @access public + */ + public function closeOr() + { + $condition = $this->orConditions[$this->orConditionOffset]->build(); + $this->orConditionOffset--; + + if ($this->orConditionOffset > 0) { + $this->orConditions[$this->orConditionOffset]->withCondition($condition); + } else { + $this->conditions[] = $condition; + } + } + + /** + * Equal condition + * + * @access public + * @param string $column + * @param mixed $value + */ + public function eq($column, $value) + { + $this->addCondition($this->db->escapeIdentifier($column).' = ?'); + $this->values[] = $value; + } + + /** + * Not equal condition + * + * @access public + * @param string $column + * @param mixed $value + */ + public function neq($column, $value) + { + $this->addCondition($this->db->escapeIdentifier($column).' != ?'); + $this->values[] = $value; + } + + /** + * IN condition + * + * @access public + * @param string $column + * @param array $values + */ + public function in($column, array $values) + { + if (! empty($values)) { + $this->addCondition($this->db->escapeIdentifier($column).' IN ('.implode(', ', array_fill(0, count($values), '?')).')'); + $this->values = array_merge($this->values, $values); + } + } + + /** + * IN condition with a subquery + * + * @access public + * @param string $column + * @param Table $subquery + */ + public function inSubquery($column, Table $subquery) + { + $this->addCondition($this->db->escapeIdentifier($column).' IN ('.$subquery->buildSelectQuery().')'); + $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues()); + } + + /** + * NOT IN condition + * + * @access public + * @param string $column + * @param array $values + */ + public function notIn($column, array $values) + { + if (! empty($values)) { + $this->addCondition($this->db->escapeIdentifier($column).' NOT IN ('.implode(', ', array_fill(0, count($values), '?')).')'); + $this->values = array_merge($this->values, $values); + } + } + + /** + * NOT IN condition with a subquery + * + * @access public + * @param string $column + * @param Table $subquery + */ + public function notInSubquery($column, Table $subquery) + { + $this->addCondition($this->db->escapeIdentifier($column).' NOT IN ('.$subquery->buildSelectQuery().')'); + $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues()); + } + + /** + * LIKE condition + * + * @access public + * @param string $column + * @param mixed $value + */ + public function like($column, $value) + { + $this->addCondition($this->db->escapeIdentifier($column).' '.$this->db->getDriver()->getOperator('LIKE').' ?'); + $this->values[] = $value; + } + + /** + * ILIKE condition + * + * @access public + * @param string $column + * @param mixed $value + */ + public function ilike($column, $value) + { + $this->addCondition($this->db->escapeIdentifier($column).' '.$this->db->getDriver()->getOperator('ILIKE').' ?'); + $this->values[] = $value; + } + + /** + * Greater than condition + * + * @access public + * @param string $column + * @param mixed $value + */ + public function gt($column, $value) + { + $this->addCondition($this->db->escapeIdentifier($column).' > ?'); + $this->values[] = $value; + } + + /** + * Greater than condition with subquery + * + * @access public + * @param string $column + * @param Table $subquery + */ + public function gtSubquery($column, Table $subquery) + { + $this->addCondition($this->db->escapeIdentifier($column).' > ('.$subquery->buildSelectQuery().')'); + $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues()); + } + + /** + * Lower than condition + * + * @access public + * @param string $column + * @param mixed $value + */ + public function lt($column, $value) + { + $this->addCondition($this->db->escapeIdentifier($column).' < ?'); + $this->values[] = $value; + } + + /** + * Lower than condition with subquery + * + * @access public + * @param string $column + * @param Table $subquery + */ + public function ltSubquery($column, Table $subquery) + { + $this->addCondition($this->db->escapeIdentifier($column).' < ('.$subquery->buildSelectQuery().')'); + $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues()); + } + + /** + * Greater than or equals condition + * + * @access public + * @param string $column + * @param mixed $value + */ + public function gte($column, $value) + { + $this->addCondition($this->db->escapeIdentifier($column).' >= ?'); + $this->values[] = $value; + } + + /** + * Greater than or equal condition with subquery + * + * @access public + * @param string $column + * @param Table $subquery + */ + public function gteSubquery($column, Table $subquery) + { + $this->addCondition($this->db->escapeIdentifier($column).' >= ('.$subquery->buildSelectQuery().')'); + $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues()); + } + + /** + * Lower than or equals condition + * + * @access public + * @param string $column + * @param mixed $value + */ + public function lte($column, $value) + { + $this->addCondition($this->db->escapeIdentifier($column).' <= ?'); + $this->values[] = $value; + } + + /** + * Lower than or equal condition with subquery + * + * @access public + * @param string $column + * @param Table $subquery + */ + public function lteSubquery($column, Table $subquery) + { + $this->addCondition($this->db->escapeIdentifier($column).' <= ('.$subquery->buildSelectQuery().')'); + $this->values = array_merge($this->values, $subquery->getConditionBuilder()->getValues()); + } + + /** + * IS NULL condition + * + * @access public + * @param string $column + */ + public function isNull($column) + { + $this->addCondition($this->db->escapeIdentifier($column).' IS NULL'); + } + + /** + * IS NOT NULL condition + * + * @access public + * @param string $column + */ + public function notNull($column) + { + $this->addCondition($this->db->escapeIdentifier($column).' IS NOT NULL'); + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Builder/InsertBuilder.php b/vendor/fguillot/picodb/lib/PicoDb/Builder/InsertBuilder.php new file mode 100644 index 00000000..9d06c405 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Builder/InsertBuilder.php @@ -0,0 +1,36 @@ +columns as $column) { + $columns[] = $this->db->escapeIdentifier($column); + $placeholders[] = ':'.$column; + } + + return sprintf( + 'INSERT INTO %s (%s) VALUES (%s)', + $this->db->escapeIdentifier($this->table), + implode(', ', $columns), + implode(', ', $placeholders) + ); + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Builder/OrConditionBuilder.php b/vendor/fguillot/picodb/lib/PicoDb/Builder/OrConditionBuilder.php new file mode 100644 index 00000000..0defeaf4 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Builder/OrConditionBuilder.php @@ -0,0 +1,43 @@ +conditions[] = $condition; + return $this; + } + + /** + * Build SQL + * + * @access public + * @return string + */ + public function build() + { + return '('.implode(' OR ', $this->conditions).')'; + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Builder/UpdateBuilder.php b/vendor/fguillot/picodb/lib/PicoDb/Builder/UpdateBuilder.php new file mode 100644 index 00000000..300ea9b0 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Builder/UpdateBuilder.php @@ -0,0 +1,56 @@ +sumColumns = $columns; + return $this; + } + + /** + * Build SQL + * + * @access public + * @return string + */ + public function build() + { + $columns = array(); + + foreach ($this->columns as $column) { + $columns[] = $this->db->escapeIdentifier($column).'=?'; + } + + foreach ($this->sumColumns as $column) { + $columns[] = $this->db->escapeIdentifier($column).'='.$this->db->escapeIdentifier($column).' + ?'; + } + + return sprintf( + 'UPDATE %s SET %s %s', + $this->db->escapeIdentifier($this->table), + implode(', ', $columns), + $this->conditionBuilder->build() + ); + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Database.php b/vendor/fguillot/picodb/lib/PicoDb/Database.php new file mode 100644 index 00000000..22c9d2fb --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Database.php @@ -0,0 +1,370 @@ +driver = DriverFactory::getDriver($settings); + $this->statementHandler = new StatementHandler($this); + } + + /** + * Destructor + * + * @access public + */ + public function __destruct() + { + $this->closeConnection(); + } + + /** + * Register a new database instance + * + * @static + * @access public + * @param string $name Instance name + * @param Closure $callback Callback + */ + public static function setInstance($name, Closure $callback) + { + self::$instances[$name] = $callback; + } + + /** + * Get a database instance + * + * @static + * @access public + * @param string $name Instance name + * @return Database + */ + public static function getInstance($name) + { + if (! isset(self::$instances[$name])) { + throw new LogicException('No database instance created with that name'); + } + + if (is_callable(self::$instances[$name])) { + self::$instances[$name] = call_user_func(self::$instances[$name]); + } + + return self::$instances[$name]; + } + + /** + * Add a log message + * + * @access public + * @param mixed $message + * @return Database + */ + public function setLogMessage($message) + { + $this->logs[] = is_array($message) ? var_export($message, true) : $message; + return $this; + } + + /** + * Add many log messages + * + * @access public + * @param array $messages + * @return Database + */ + public function setLogMessages(array $messages) + { + foreach ($messages as $message) { + $this->setLogMessage($message); + } + + return $this; + } + + /** + * Get all queries logs + * + * @access public + * @return array + */ + public function getLogMessages() + { + return $this->logs; + } + + /** + * Get the PDO connection + * + * @access public + * @return \PDO + */ + public function getConnection() + { + return $this->driver->getConnection(); + } + + /** + * Get the Driver instance + * + * @access public + * @return Mssql|Sqlite|Postgres|Mysql + */ + public function getDriver() + { + return $this->driver; + } + + /** + * Get the last inserted id + * + * @access public + * @return integer + */ + public function getLastId() + { + return (int) $this->driver->getLastId(); + } + + /** + * Get statement object + * + * @access public + * @return StatementHandler + */ + public function getStatementHandler() + { + return $this->statementHandler; + } + + /** + * Release the PDO connection + * + * @access public + */ + public function closeConnection() + { + $this->driver->closeConnection(); + } + + /** + * Escape an identifier (column, table name...) + * + * @access public + * @param string $value Value + * @param string $table Table name + * @return string + */ + public function escapeIdentifier($value, $table = '') + { + // Do not escape custom query + if (strpos($value, '.') !== false || strpos($value, ' ') !== false) { + return $value; + } + + if (! empty($table)) { + return $this->driver->escape($table).'.'.$this->driver->escape($value); + } + + return $this->driver->escape($value); + } + + /** + * Escape an identifier list + * + * @access public + * @param array $identifiers List of identifiers + * @param string $table Table name + * @return string[] + */ + public function escapeIdentifierList(array $identifiers, $table = '') + { + foreach ($identifiers as $key => $value) { + $identifiers[$key] = $this->escapeIdentifier($value, $table); + } + + return $identifiers; + } + + /** + * Execute a prepared statement + * + * Note: returns false on duplicate keys instead of SQLException + * + * @access public + * @param string $sql SQL query + * @param array $values Values + * @return \PDOStatement|false + */ + public function execute($sql, array $values = array()) + { + return $this->statementHandler + ->withSql($sql) + ->withPositionalParams($values) + ->execute(); + } + + /** + * Run a transaction + * + * @access public + * @param Closure $callback Callback + * @return mixed + */ + public function transaction(Closure $callback) + { + try { + + $this->startTransaction(); + $result = $callback($this); + $this->closeTransaction(); + + return $result === null ? true : $result; + } catch (PDOException $e) { + return $this->statementHandler->handleSqlError($e); + } + } + + /** + * Begin a transaction + * + * @access public + */ + public function startTransaction() + { + if (! $this->getConnection()->inTransaction()) { + $this->getConnection()->beginTransaction(); + } + } + + /** + * Commit a transaction + * + * @access public + */ + public function closeTransaction() + { + if ($this->getConnection()->inTransaction()) { + $this->getConnection()->commit(); + } + } + + /** + * Rollback a transaction + * + * @access public + */ + public function cancelTransaction() + { + if ($this->getConnection()->inTransaction()) { + $this->getConnection()->rollBack(); + } + } + + /** + * Get a table object + * + * @access public + * @param string $table + * @return Table + */ + public function table($table) + { + return new Table($this, $table); + } + + /** + * Get a hashtable object + * + * @access public + * @param string $table + * @return Hashtable + */ + public function hashtable($table) + { + return new Hashtable($this, $table); + } + + /** + * Get a LOB object + * + * @access public + * @param string $table + * @return LargeObject + */ + public function largeObject($table) + { + return new LargeObject($this, $table); + } + + /** + * Get a schema object + * + * @access public + * @param string $namespace + * @return Schema + */ + public function schema($namespace = null) + { + $schema = new Schema($this); + + if ($namespace !== null) { + $schema->setNamespace($namespace); + } + + return $schema; + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Base.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Base.php new file mode 100644 index 00000000..790cd623 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Base.php @@ -0,0 +1,234 @@ +requiredAttributes as $attribute) { + if (! isset($settings[$attribute])) { + throw new LogicException('This configuration parameter is missing: "'.$attribute.'"'); + } + } + + $this->createConnection($settings); + $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } + + /** + * Get the PDO connection + * + * @access public + * @return PDO + */ + public function getConnection() + { + return $this->pdo; + } + + /** + * Release the PDO connection + * + * @access public + */ + public function closeConnection() + { + $this->pdo = null; + } + + /** + * Upsert for a key/value variable + * + * @access public + * @param string $table + * @param string $keyColumn + * @param string $valueColumn + * @param array $dictionary + * @return bool False on failure + */ + public function upsert($table, $keyColumn, $valueColumn, array $dictionary) + { + try { + $this->pdo->beginTransaction(); + + foreach ($dictionary as $key => $value) { + + $rq = $this->pdo->prepare('SELECT 1 FROM '.$this->escape($table).' WHERE '.$this->escape($keyColumn).'=?'); + $rq->execute(array($key)); + + if ($rq->fetchColumn()) { + $rq = $this->pdo->prepare('UPDATE '.$this->escape($table).' SET '.$this->escape($valueColumn).'=? WHERE '.$this->escape($keyColumn).'=?'); + $rq->execute(array($value, $key)); + } + else { + $rq = $this->pdo->prepare('INSERT INTO '.$this->escape($table).' ('.$this->escape($keyColumn).', '.$this->escape($valueColumn).') VALUES (?, ?)'); + $rq->execute(array($key, $value)); + } + } + + $this->pdo->commit(); + + return true; + } + catch (PDOException $e) { + $this->pdo->rollBack(); + return false; + } + } + + /** + * Run EXPLAIN command + * + * @access public + * @param string $sql + * @param array $values + * @return array + */ + public function explain($sql, array $values) + { + return $this->getConnection()->query('EXPLAIN '.$this->getSqlFromPreparedStatement($sql, $values))->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Replace placeholder with values in prepared statement + * + * @access protected + * @param string $sql + * @param array $values + * @return string + */ + protected function getSqlFromPreparedStatement($sql, array $values) + { + foreach ($values as $value) { + $sql = substr_replace($sql, "'$value'", strpos($sql, '?'), 1); + } + + return $sql; + } + + /** + * Get database version + * + * @access public + * @return array + */ + public function getDatabaseVersion() + { + return $this->getConnection()->query('SELECT VERSION()')->fetchColumn(); + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Mssql.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Mssql.php new file mode 100644 index 00000000..83e75af2 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Mssql.php @@ -0,0 +1,178 @@ + + */ +class Mssql extends Base +{ + /** + * List of required settings options + * + * @access protected + * @var array + */ + protected $requiredAttributes = array( + 'hostname', + 'username', + 'password', + 'database', + ); + + /** + * Table to store the schema version + * + * @access private + * @var array + */ + private $schemaTable = 'schema_version'; + + /** + * Create a new PDO connection + * + * @access public + * @param array $settings + */ + public function createConnection(array $settings) + { + $dsn = 'sqlsrv:Server=' . $settings['hostname'] . ';Database=' . $settings['database']; + + if (! empty($settings['port'])) { + $dsn .= ';port=' . $settings['port']; + } + + $this->pdo = new PDO($dsn, $settings['username'], $settings['password']); + + if (isset($settings['schema_table'])) { + $this->schemaTable = $settings['schema_table']; + } + } + + /** + * Enable foreign keys + * + * @access public + */ + public function enableForeignKeys() + { + $this->pdo->exec('EXEC sp_MSforeachtable @command1="ALTER TABLE ? CHECK CONSTRAINT ALL"; GO;'); + } + + /** + * Disable foreign keys + * + * @access public + */ + public function disableForeignKeys() + { + $this->pdo->exec('EXEC sp_MSforeachtable @command1="ALTER TABLE ? NOCHECK CONSTRAINT ALL"; GO;'); + } + + /** + * Return true if the error code is a duplicate key + * + * @access public + * @param integer $code + * @return boolean + */ + public function isDuplicateKeyError($code) + { + return $code == 2601; + } + + /** + * Escape identifier + * + * https://msdn.microsoft.com/en-us/library/ms175874.aspx + * + * @access public + * @param string $identifier + * @return string + */ + public function escape($identifier) + { + return '['.$identifier.']'; + } + + /** + * Get non standard operator + * + * @access public + * @param string $operator + * @return string + */ + public function getOperator($operator) + { + if ($operator === 'LIKE' || $operator === 'ILIKE') { + return 'LIKE'; + } + + return ''; + } + + /** + * Get last inserted id + * + * @access public + * @return integer + */ + public function getLastId() + { + return $this->pdo->lastInsertId(); + } + + /** + * Get current schema version + * + * @access public + * @return integer + */ + public function getSchemaVersion() + { + $this->pdo->exec("CREATE TABLE IF NOT EXISTS [".$this->schemaTable."] ([version] INT DEFAULT '0')"); + + $rq = $this->pdo->prepare('SELECT [version] FROM ['.$this->schemaTable.']'); + $rq->execute(); + $result = $rq->fetchColumn(); + + if ($result !== false) { + return (int) $result; + } + else { + $this->pdo->exec('INSERT INTO ['.$this->schemaTable.'] VALUES(0)'); + } + + return 0; + } + + /** + * Set current schema version + * + * @access public + * @param integer $version + */ + public function setSchemaVersion($version) + { + $rq = $this->pdo->prepare('UPDATE ['.$this->schemaTable.'] SET [version]=?'); + $rq->execute(array($version)); + } + + /** + * Run EXPLAIN command + * + * @param string $sql + * @param array $values + * @return array + */ + public function explain($sql, array $values) + { + $this->getConnection()->exec('SET SHOWPLAN_ALL ON'); + return $this->getConnection()->query($this->getSqlFromPreparedStatement($sql, $values))->fetchAll(PDO::FETCH_ASSOC); + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php new file mode 100644 index 00000000..4f3ca64e --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Mysql.php @@ -0,0 +1,252 @@ +pdo = new PDO( + $this->buildDsn($settings), + $settings['username'], + $settings['password'], + $this->buildOptions($settings) + ); + + if (isset($settings['schema_table'])) { + $this->schemaTable = $settings['schema_table']; + } + } + + /** + * Build connection DSN + * + * @access protected + * @param array $settings + * @return string + */ + protected function buildDsn(array $settings) + { + $charset = empty($settings['charset']) ? 'utf8' : $settings['charset']; + $dsn = 'mysql:host='.$settings['hostname'].';dbname='.$settings['database'].';charset='.$charset; + + if (! empty($settings['port'])) { + $dsn .= ';port='.$settings['port']; + } + + return $dsn; + } + + /** + * Build connection options + * + * @access protected + * @param array $settings + * @return array + */ + protected function buildOptions(array $settings) + { + $options = array( + PDO::MYSQL_ATTR_INIT_COMMAND => 'SET sql_mode = STRICT_ALL_TABLES', + ); + + if (! empty($settings['ssl_key'])) { + $options[PDO::MYSQL_ATTR_SSL_KEY] = $settings['ssl_key']; + } + + if (! empty($settings['ssl_cert'])) { + $options[PDO::MYSQL_ATTR_SSL_CERT] = $settings['ssl_cert']; + } + + if (! empty($settings['ssl_ca'])) { + $options[PDO::MYSQL_ATTR_SSL_CA] = $settings['ssl_ca']; + } + + return $options; + } + + /** + * Enable foreign keys + * + * @access public + */ + public function enableForeignKeys() + { + $this->pdo->exec('SET FOREIGN_KEY_CHECKS=1'); + } + + /** + * Disable foreign keys + * + * @access public + */ + public function disableForeignKeys() + { + $this->pdo->exec('SET FOREIGN_KEY_CHECKS=0'); + } + + /** + * Return true if the error code is a duplicate key + * + * @access public + * @param integer $code + * @return boolean + */ + public function isDuplicateKeyError($code) + { + return $code == 23000; + } + + /** + * Escape identifier + * + * @access public + * @param string $identifier + * @return string + */ + public function escape($identifier) + { + return '`'.$identifier.'`'; + } + + /** + * Get non standard operator + * + * @access public + * @param string $operator + * @return string + */ + public function getOperator($operator) + { + if ($operator === 'LIKE') { + return 'LIKE BINARY'; + } + else if ($operator === 'ILIKE') { + return 'LIKE'; + } + + return ''; + } + + /** + * Get last inserted id + * + * @access public + * @return integer + */ + public function getLastId() + { + return $this->pdo->lastInsertId(); + } + + /** + * Get current schema version + * + * @access public + * @return integer + */ + public function getSchemaVersion() + { + $this->pdo->exec("CREATE TABLE IF NOT EXISTS `".$this->schemaTable."` (`version` INT DEFAULT '0') ENGINE=InnoDB CHARSET=utf8"); + + $rq = $this->pdo->prepare('SELECT `version` FROM `'.$this->schemaTable.'`'); + $rq->execute(); + $result = $rq->fetchColumn(); + + if ($result !== false) { + return (int) $result; + } + else { + $this->pdo->exec('INSERT INTO `'.$this->schemaTable.'` VALUES(0)'); + } + + return 0; + } + + /** + * Set current schema version + * + * @access public + * @param integer $version + */ + public function setSchemaVersion($version) + { + $rq = $this->pdo->prepare('UPDATE `'.$this->schemaTable.'` SET `version`=?'); + $rq->execute(array($version)); + } + + /** + * Upsert for a key/value variable + * + * @access public + * @param string $table + * @param string $keyColumn + * @param string $valueColumn + * @param array $dictionary + * @return bool False on failure + */ + public function upsert($table, $keyColumn, $valueColumn, array $dictionary) + { + try { + + $sql = sprintf( + 'REPLACE INTO %s (%s, %s) VALUES %s', + $this->escape($table), + $this->escape($keyColumn), + $this->escape($valueColumn), + implode(', ', array_fill(0, count($dictionary), '(?, ?)')) + ); + + $values = array(); + + foreach ($dictionary as $key => $value) { + $values[] = $key; + $values[] = $value; + } + + $rq = $this->pdo->prepare($sql); + $rq->execute($values); + + return true; + } + catch (PDOException $e) { + return false; + } + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php new file mode 100644 index 00000000..a494cdca --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Postgres.php @@ -0,0 +1,196 @@ +pdo = new PDO($dsn, $settings['username'], $settings['password']); + + if (isset($settings['schema_table'])) { + $this->schemaTable = $settings['schema_table']; + } + } + + /** + * Enable foreign keys + * + * @access public + */ + public function enableForeignKeys() + { + } + + /** + * Disable foreign keys + * + * @access public + */ + public function disableForeignKeys() + { + } + + /** + * Return true if the error code is a duplicate key + * + * @access public + * @param integer $code + * @return boolean + */ + public function isDuplicateKeyError($code) + { + return $code == 23505 || $code == 23503; + } + + /** + * Escape identifier + * + * @access public + * @param string $identifier + * @return string + */ + public function escape($identifier) + { + return '"'.$identifier.'"'; + } + + /** + * Get non standard operator + * + * @access public + * @param string $operator + * @return string + */ + public function getOperator($operator) + { + if ($operator === 'LIKE') { + return 'LIKE'; + } + else if ($operator === 'ILIKE') { + return 'ILIKE'; + } + + return ''; + } + + /** + * Get last inserted id + * + * @access public + * @return integer + */ + public function getLastId() + { + try { + $rq = $this->pdo->prepare('SELECT LASTVAL()'); + $rq->execute(); + + return $rq->fetchColumn(); + } + catch (PDOException $e) { + return 0; + } + } + + /** + * Get current schema version + * + * @access public + * @return integer + */ + public function getSchemaVersion() + { + $this->pdo->exec("CREATE TABLE IF NOT EXISTS ".$this->schemaTable." (version INTEGER DEFAULT 0)"); + + $rq = $this->pdo->prepare('SELECT "version" FROM "'.$this->schemaTable.'"'); + $rq->execute(); + $result = $rq->fetchColumn(); + + if ($result !== false) { + return (int) $result; + } + else { + $this->pdo->exec('INSERT INTO '.$this->schemaTable.' VALUES(0)'); + } + + return 0; + } + + /** + * Set current schema version + * + * @access public + * @param integer $version + */ + public function setSchemaVersion($version) + { + $rq = $this->pdo->prepare('UPDATE '.$this->schemaTable.' SET version=?'); + $rq->execute(array($version)); + } + + /** + * Run EXPLAIN command + * + * @param string $sql + * @param array $values + * @return array + */ + public function explain($sql, array $values) + { + return $this->getConnection()->query('EXPLAIN (FORMAT YAML) '.$this->getSqlFromPreparedStatement($sql, $values))->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Get database version + * + * @access public + * @return array + */ + public function getDatabaseVersion() + { + return $this->getConnection()->query('SHOW server_version')->fetchColumn(); + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php b/vendor/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php new file mode 100644 index 00000000..ea39f007 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Driver/Sqlite.php @@ -0,0 +1,193 @@ +pdo = new PDO('sqlite:'.$settings['filename']); + $this->enableForeignKeys(); + } + + /** + * Enable foreign keys + * + * @access public + */ + public function enableForeignKeys() + { + $this->pdo->exec('PRAGMA foreign_keys = ON'); + } + + /** + * Disable foreign keys + * + * @access public + */ + public function disableForeignKeys() + { + $this->pdo->exec('PRAGMA foreign_keys = OFF'); + } + + /** + * Return true if the error code is a duplicate key + * + * @access public + * @param integer $code + * @return boolean + */ + public function isDuplicateKeyError($code) + { + return $code == 23000; + } + + /** + * Escape identifier + * + * @access public + * @param string $identifier + * @return string + */ + public function escape($identifier) + { + return '"'.$identifier.'"'; + } + + /** + * Get non standard operator + * + * @access public + * @param string $operator + * @return string + */ + public function getOperator($operator) + { + if ($operator === 'LIKE' || $operator === 'ILIKE') { + return 'LIKE'; + } + + return ''; + } + + /** + * Get last inserted id + * + * @access public + * @return integer + */ + public function getLastId() + { + return $this->pdo->lastInsertId(); + } + + /** + * Get current schema version + * + * @access public + * @return integer + */ + public function getSchemaVersion() + { + $rq = $this->pdo->prepare('PRAGMA user_version'); + $rq->execute(); + + return (int) $rq->fetchColumn(); + } + + /** + * Set current schema version + * + * @access public + * @param integer $version + */ + public function setSchemaVersion($version) + { + $this->pdo->exec('PRAGMA user_version='.$version); + } + + /** + * Upsert for a key/value variable + * + * @access public + * @param string $table + * @param string $keyColumn + * @param string $valueColumn + * @param array $dictionary + * @return bool False on failure + */ + public function upsert($table, $keyColumn, $valueColumn, array $dictionary) + { + try { + $this->pdo->beginTransaction(); + + foreach ($dictionary as $key => $value) { + + $sql = sprintf( + 'INSERT OR REPLACE INTO %s (%s, %s) VALUES (?, ?)', + $this->escape($table), + $this->escape($keyColumn), + $this->escape($valueColumn) + ); + + $rq = $this->pdo->prepare($sql); + $rq->execute(array($key, $value)); + } + + $this->pdo->commit(); + + return true; + } + catch (PDOException $e) { + $this->pdo->rollBack(); + return false; + } + } + + /** + * Run EXPLAIN command + * + * @access public + * @param string $sql + * @param array $values + * @return array + */ + public function explain($sql, array $values) + { + return $this->getConnection()->query('EXPLAIN QUERY PLAN '.$this->getSqlFromPreparedStatement($sql, $values))->fetchAll(PDO::FETCH_ASSOC); + } + + /** + * Get database version + * + * @access public + * @return array + */ + public function getDatabaseVersion() + { + return $this->getConnection()->query('SELECT sqlite_version()')->fetchColumn(); + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/DriverFactory.php b/vendor/fguillot/picodb/lib/PicoDb/DriverFactory.php new file mode 100644 index 00000000..13151ba7 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/DriverFactory.php @@ -0,0 +1,45 @@ +keyColumn = $column; + return $this; + } + + /** + * Set the value column + * + * @access public + * @param string $column + * @return $this + */ + public function columnValue($column) + { + $this->valueColumn = $column; + return $this; + } + + /** + * Insert or update + * + * @access public + * @param array $hashmap + * @return boolean + */ + public function put(array $hashmap) + { + return $this->db->getDriver()->upsert($this->getName(), $this->keyColumn, $this->valueColumn, $hashmap); + } + + /** + * Hashmap result [ [column1 => column2], [], ...] + * + * @access public + * @return array + */ + public function get() + { + $hashmap = array(); + + // setup where condition + if (func_num_args() > 0) { + $this->in($this->keyColumn, func_get_args()); + } + + // setup to select columns in case that there are more than two + $this->columns($this->keyColumn, $this->valueColumn); + + $rq = $this->db->execute($this->buildSelectQuery(), $this->conditionBuilder->getValues()); + $rows = $rq->fetchAll(PDO::FETCH_NUM); + + foreach ($rows as $row) { + $hashmap[$row[0]] = $row[1]; + } + + return $hashmap; + } + + /** + * Shortcut method to get a hashmap result + * + * @access public + * @param string $key Key column + * @param string $value Value column + * @return array + */ + public function getAll($key, $value) + { + $this->keyColumn = $key; + $this->valueColumn = $value; + return $this->get(); + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/LargeObject.php b/vendor/fguillot/picodb/lib/PicoDb/LargeObject.php new file mode 100644 index 00000000..ba5e3b92 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/LargeObject.php @@ -0,0 +1,167 @@ +limit(1); + $this->columns($column); + + $rq = $this->db->getStatementHandler() + ->withSql($this->buildSelectQuery()) + ->withPositionalParams($this->conditionBuilder->getValues()) + ->execute(); + + $rq->bindColumn($column, $fd, PDO::PARAM_LOB); + $rq->fetch(PDO::FETCH_BOUND); + + return $fd; + } + + /** + * Fetch large object as string + * + * @access public + * @param string $column + * @return string + */ + public function findOneColumnAsString($column) + { + $fd = $this->findOneColumnAsStream($column); + + if (is_string($fd)) { + return $fd; + } + + return stream_get_contents($fd); + } + + /** + * Insert large object from stream + * + * @access public + * @param string $blobColumn + * @param resource|string $blobDescriptor + * @param array $data + * @return bool + */ + public function insertFromStream($blobColumn, &$blobDescriptor, array $data = array()) + { + $columns = array_merge(array($blobColumn), array_keys($data)); + $this->db->startTransaction(); + + $result = $this->db->getStatementHandler() + ->withSql(InsertBuilder::getInstance($this->db, $this->conditionBuilder) + ->withTable($this->name) + ->withColumns($columns) + ->build() + ) + ->withNamedParams($data) + ->withLobParam($blobColumn, $blobDescriptor) + ->execute(); + + $this->db->closeTransaction(); + + return $result !== false; + } + + /** + * Insert large object from file + * + * @access public + * @param string $blobColumn + * @param string $filename + * @param array $data + * @return bool + */ + public function insertFromFile($blobColumn, $filename, array $data = array()) + { + $fp = fopen($filename, 'rb'); + $result = $this->insertFromStream($blobColumn, $fp, $data); + fclose($fp); + return $result; + } + + /** + * Insert large object from string + * + * @access public + * @param string $blobColumn + * @param string $blobData + * @param array $data + * @return bool + */ + public function insertFromString($blobColumn, &$blobData, array $data = array()) + { + return $this->insertFromStream($blobColumn, $blobData, $data); + } + + /** + * Update large object from stream + * + * @access public + * @param string $blobColumn + * @param resource $blobDescriptor + * @param array $data + * @return bool + */ + public function updateFromStream($blobColumn, &$blobDescriptor, array $data = array()) + { + $values = array_merge(array_values($data), $this->conditionBuilder->getValues()); + $columns = array_merge(array($blobColumn), array_keys($data)); + + $this->db->startTransaction(); + + $result = $this->db->getStatementHandler() + ->withSql(UpdateBuilder::getInstance($this->db, $this->conditionBuilder) + ->withTable($this->name) + ->withColumns($columns) + ->build() + ) + ->withPositionalParams($values) + ->withLobParam($blobColumn, $blobDescriptor) + ->execute(); + + $this->db->closeTransaction(); + + return $result !== false; + } + + /** + * Update large object from file + * + * @access public + * @param string $blobColumn + * @param string $filename + * @param array $data + * @return bool + */ + public function updateFromFile($blobColumn, $filename, array $data = array()) + { + $fp = fopen($filename, 'r'); + $result = $this->updateFromStream($blobColumn, $fp, $data); + fclose($fp); + return $result; + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/SQLException.php b/vendor/fguillot/picodb/lib/PicoDb/SQLException.php new file mode 100644 index 00000000..7e570834 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/SQLException.php @@ -0,0 +1,15 @@ +db = $db; + } + + /** + * Set another namespace + * + * @access public + * @param string $namespace + * @return Schema + */ + public function setNamespace($namespace) + { + $this->namespace = $namespace; + return $this; + } + + /** + * Get schema namespace + * + * @access public + * @return string + */ + public function getNamespace() + { + return $this->namespace; + } + + /** + * Check the schema version and run the migrations + * + * @access public + * @param integer $last_version + * @return boolean + */ + public function check($last_version = 1) + { + $current_version = $this->db->getDriver()->getSchemaVersion(); + + if ($current_version < $last_version) { + return $this->migrateTo($current_version, $last_version); + } + + return true; + } + + /** + * Migrate the schema to one version to another + * + * @access public + * @param integer $current_version + * @param integer $next_version + * @return boolean + */ + public function migrateTo($current_version, $next_version) + { + try { + for ($i = $current_version + 1; $i <= $next_version; $i++) { + $this->db->startTransaction(); + $this->db->getDriver()->disableForeignKeys(); + + $function_name = $this->getNamespace().'\version_'.$i; + + if (function_exists($function_name)) { + $this->db->setLogMessage('Running migration '.$function_name); + call_user_func($function_name, $this->db->getConnection()); + } + + $this->db->getDriver()->setSchemaVersion($i); + $this->db->getDriver()->enableForeignKeys(); + $this->db->closeTransaction(); + } + } catch (PDOException $e) { + $this->db->setLogMessage($e->getMessage()); + $this->db->cancelTransaction(); + $this->db->getDriver()->enableForeignKeys(); + return false; + } + + return true; + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/StatementHandler.php b/vendor/fguillot/picodb/lib/PicoDb/StatementHandler.php new file mode 100644 index 00000000..a7021b36 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/StatementHandler.php @@ -0,0 +1,353 @@ +db = $db; + } + + /** + * Enable query logging + * + * @access public + * @return $this + */ + public function withLogging() + { + $this->logQueries = true; + return $this; + } + + /** + * Record query execution time + * + * @access public + * @return $this + */ + public function withStopWatch() + { + $this->stopwatch = true; + return $this; + } + + /** + * Execute explain command on query + * + * @access public + * @return $this + */ + public function withExplain() + { + $this->explain = true; + return $this; + } + + /** + * Set SQL query + * + * @access public + * @param string $sql + * @return $this + */ + public function withSql($sql) + { + $this->sql = $sql; + return $this; + } + + /** + * Set positional parameters + * + * @access public + * @param array $params + * @return $this + */ + public function withPositionalParams(array $params) + { + $this->positionalParams = $params; + return $this; + } + + /** + * Set named parameters + * + * @access public + * @param array $params + * @return $this + */ + public function withNamedParams(array $params) + { + $this->namedParams = $params; + $this->useNamedParams = true; + return $this; + } + + /** + * Bind large object parameter + * + * @access public + * @param $name + * @param $fp + * @return $this + */ + public function withLobParam($name, &$fp) + { + $this->lobParams[$name] =& $fp; + return $this; + } + + /** + * Get number of queries executed + * + * @access public + * @return int + */ + public function getNbQueries() + { + return $this->nbQueries; + } + + /** + * Execute a prepared statement + * + * Note: returns false on duplicate keys instead of SQLException + * + * @access public + * @return PDOStatement|false + */ + public function execute() + { + try { + $this->beforeExecute(); + + $pdoStatement = $this->db->getConnection()->prepare($this->sql); + $this->bindParams($pdoStatement); + $pdoStatement->execute(); + + $this->afterExecute(); + return $pdoStatement; + } catch (PDOException $e) { + return $this->handleSqlError($e); + } + } + + /** + * Bind parameters to PDOStatement + * + * @access protected + * @param PDOStatement $pdoStatement + */ + protected function bindParams(PDOStatement $pdoStatement) + { + $i = 1; + + foreach ($this->lobParams as $name => $variable) { + if (! $this->useNamedParams) { + $parameter = $i; + $i++; + } else { + $parameter = $name; + } + + $pdoStatement->bindParam($parameter, $variable, PDO::PARAM_LOB); + } + + foreach ($this->positionalParams as $value) { + $pdoStatement->bindValue($i, $value, PDO::PARAM_STR); + $i++; + } + + foreach ($this->namedParams as $name => $value) { + $pdoStatement->bindValue($name, $value, PDO::PARAM_STR); + } + } + + /** + * Method executed before query execution + * + * @access protected + */ + protected function beforeExecute() + { + if ($this->logQueries) { + $this->db->setLogMessage($this->sql); + } + + if ($this->stopwatch) { + $this->startTime = microtime(true); + } + } + + /** + * Method executed after query execution + * + * @access protected + */ + protected function afterExecute() + { + if ($this->stopwatch) { + $duration = microtime(true) - $this->startTime; + $this->executionTime += $duration; + $this->db->setLogMessage('query_duration='.$duration); + $this->db->setLogMessage('total_execution_time='.$this->executionTime); + } + + if ($this->explain) { + $this->db->setLogMessages($this->db->getDriver()->explain($this->sql, $this->positionalParams)); + } + + $this->nbQueries++; + $this->cleanup(); + } + + /** + * Reset internal properties after execution + * The same object instance is used + * + * @access protected + */ + protected function cleanup() + { + $this->sql = ''; + $this->useNamedParams = false; + $this->positionalParams = array(); + $this->namedParams = array(); + $this->lobParams = array(); + } + + /** + * Handle PDOException + * + * @access public + * @param PDOException $e + * @return bool + * @throws SQLException + */ + public function handleSqlError(PDOException $e) + { + $this->cleanup(); + $this->db->cancelTransaction(); + $this->db->setLogMessage($e->getMessage()); + + if ($this->db->getDriver()->isDuplicateKeyError($e->getCode())) { + return false; + } + + throw new SQLException('SQL error'.($this->logQueries ? ': '.$e->getMessage() : '')); + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/Table.php b/vendor/fguillot/picodb/lib/PicoDb/Table.php new file mode 100644 index 00000000..09eb928e --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/Table.php @@ -0,0 +1,721 @@ +db = $db; + $this->name = $name; + $this->conditionBuilder = new ConditionBuilder($db); + } + + /** + * Return the table name + * + * @access public + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Return ConditionBuilder object + * + * @access public + * @return ConditionBuilder + */ + public function getConditionBuilder() + { + return $this->conditionBuilder; + } + + /** + * Insert or update + * + * @access public + * @param array $data + * @return boolean + */ + public function save(array $data) + { + return $this->conditionBuilder->hasCondition() ? $this->update($data) : $this->insert($data); + } + + /** + * Update + * + * @access public + * @param array $data + * @return boolean + */ + public function update(array $data = array()) + { + $values = array_merge(array_values($data), array_values($this->sumColumns), $this->conditionBuilder->getValues()); + $sql = UpdateBuilder::getInstance($this->db, $this->conditionBuilder) + ->withTable($this->name) + ->withColumns(array_keys($data)) + ->withSumColumns(array_keys($this->sumColumns)) + ->build(); + + return $this->db->execute($sql, $values) !== false; + } + + /** + * Insert + * + * @access public + * @param array $data + * @return boolean + */ + public function insert(array $data) + { + return $this->db->getStatementHandler() + ->withSql(InsertBuilder::getInstance($this->db, $this->conditionBuilder) + ->withTable($this->name) + ->withColumns(array_keys($data)) + ->build() + ) + ->withNamedParams($data) + ->execute() !== false; + } + + /** + * Insert a new row and return the ID of the primary key + * + * @access public + * @param array $data + * @return bool|int + */ + public function persist(array $data) + { + if ($this->insert($data)) { + return $this->db->getLastId(); + } + + return false; + } + + /** + * Remove + * + * @access public + * @return boolean + */ + public function remove() + { + $sql = sprintf( + 'DELETE FROM %s %s', + $this->db->escapeIdentifier($this->name), + $this->conditionBuilder->build() + ); + + $result = $this->db->execute($sql, $this->conditionBuilder->getValues()); + return $result->rowCount() > 0; + } + + /** + * Fetch all rows + * + * @access public + * @return array + */ + public function findAll() + { + $rq = $this->db->execute($this->buildSelectQuery(), $this->conditionBuilder->getValues()); + $results = $rq->fetchAll(PDO::FETCH_ASSOC); + + if (is_callable($this->callback) && ! empty($results)) { + return call_user_func($this->callback, $results); + } + + return $results; + } + + /** + * Find all with a single column + * + * @access public + * @param string $column + * @return mixed + */ + public function findAllByColumn($column) + { + $this->columns = array($column); + $rq = $this->db->execute($this->buildSelectQuery(), $this->conditionBuilder->getValues()); + + return $rq->fetchAll(PDO::FETCH_COLUMN, 0); + } + + /** + * Fetch one row + * + * @access public + * @return array|null + */ + public function findOne() + { + $this->limit(1); + $result = $this->findAll(); + + return isset($result[0]) ? $result[0] : null; + } + + /** + * Fetch one column, first row + * + * @access public + * @param string $column + * @return string + */ + public function findOneColumn($column) + { + $this->limit(1); + $this->columns = array($column); + + return $this->db->execute($this->buildSelectQuery(), $this->conditionBuilder->getValues())->fetchColumn(); + } + + /** + * Build a subquery with an alias + * + * @access public + * @param string $sql + * @param string $alias + * @return $this + */ + public function subquery($sql, $alias) + { + $this->columns[] = '('.$sql.') AS '.$this->db->escapeIdentifier($alias); + return $this; + } + + /** + * Exists + * + * @access public + * @return integer + */ + public function exists() + { + $sql = sprintf( + 'SELECT 1 FROM %s '.implode(' ', $this->joins).$this->conditionBuilder->build(), + $this->db->escapeIdentifier($this->name) + ); + + $rq = $this->db->execute($sql, $this->conditionBuilder->getValues()); + $result = $rq->fetchColumn(); + + return $result ? true : false; + } + + /** + * Count + * + * @access public + * @return integer + */ + public function count() + { + $sql = sprintf( + 'SELECT COUNT(*) FROM %s '.implode(' ', $this->joins).$this->conditionBuilder->build().$this->sqlOrder.$this->sqlLimit.$this->sqlOffset, + $this->db->escapeIdentifier($this->name) + ); + + $rq = $this->db->execute($sql, $this->conditionBuilder->getValues()); + $result = $rq->fetchColumn(); + + return $result ? (int) $result : 0; + } + + /** + * Sum + * + * @access public + * @param string $column + * @return float + */ + public function sum($column) + { + $sql = sprintf( + 'SELECT SUM(%s) FROM %s '.implode(' ', $this->joins).$this->conditionBuilder->build().$this->sqlOrder.$this->sqlLimit.$this->sqlOffset, + $this->db->escapeIdentifier($column), + $this->db->escapeIdentifier($this->name) + ); + + $rq = $this->db->execute($sql, $this->conditionBuilder->getValues()); + $result = $rq->fetchColumn(); + + return $result ? (float) $result : 0; + } + + /** + * Increment column value + * + * @access public + * @param string $column + * @param string $value + * @return boolean + */ + public function increment($column, $value) + { + $sql = sprintf( + 'UPDATE %s SET %s=%s+%d '.$this->conditionBuilder->build(), + $this->db->escapeIdentifier($this->name), + $this->db->escapeIdentifier($column), + $this->db->escapeIdentifier($column), + $value + ); + + return $this->db->execute($sql, $this->conditionBuilder->getValues()) !== false; + } + + /** + * Decrement column value + * + * @access public + * @param string $column + * @param string $value + * @return boolean + */ + public function decrement($column, $value) + { + $sql = sprintf( + 'UPDATE %s SET %s=%s-%d '.$this->conditionBuilder->build(), + $this->db->escapeIdentifier($this->name), + $this->db->escapeIdentifier($column), + $this->db->escapeIdentifier($column), + $value + ); + + return $this->db->execute($sql, $this->conditionBuilder->getValues()) !== false; + } + + /** + * Left join + * + * @access public + * @param string $table Join table + * @param string $foreign_column Foreign key on the join table + * @param string $local_column Local column + * @param string $local_table Local table + * @param string $alias Join table alias + * @return $this + */ + public function join($table, $foreign_column, $local_column, $local_table = '', $alias = '') + { + $this->joins[] = sprintf( + 'LEFT JOIN %s ON %s=%s', + $this->db->escapeIdentifier($table), + $this->db->escapeIdentifier($alias ?: $table).'.'.$this->db->escapeIdentifier($foreign_column), + $this->db->escapeIdentifier($local_table ?: $this->name).'.'.$this->db->escapeIdentifier($local_column) + ); + + return $this; + } + + /** + * Left join + * + * @access public + * @param string $table1 + * @param string $alias1 + * @param string $column1 + * @param string $table2 + * @param string $column2 + * @return $this + */ + public function left($table1, $alias1, $column1, $table2, $column2) + { + $this->joins[] = sprintf( + 'LEFT JOIN %s AS %s ON %s=%s', + $this->db->escapeIdentifier($table1), + $this->db->escapeIdentifier($alias1), + $this->db->escapeIdentifier($alias1).'.'.$this->db->escapeIdentifier($column1), + $this->db->escapeIdentifier($table2).'.'.$this->db->escapeIdentifier($column2) + ); + + return $this; + } + + /** + * Inner join + * + * @access public + * @param string $table1 + * @param string $alias1 + * @param string $column1 + * @param string $table2 + * @param string $column2 + * @return $this + */ + public function inner($table1, $alias1, $column1, $table2, $column2) + { + $this->joins[] = sprintf( + 'JOIN %s AS %s ON %s=%s', + $this->db->escapeIdentifier($table1), + $this->db->escapeIdentifier($alias1), + $this->db->escapeIdentifier($alias1).'.'.$this->db->escapeIdentifier($column1), + $this->db->escapeIdentifier($table2).'.'.$this->db->escapeIdentifier($column2) + ); + + return $this; + } + + /** + * Order by + * + * @access public + * @param string $column Column name + * @param string $order Direction ASC or DESC + * @return $this + */ + public function orderBy($column, $order = self::SORT_ASC) + { + $order = strtoupper($order); + $order = $order === self::SORT_ASC || $order === self::SORT_DESC ? $order : self::SORT_ASC; + + if ($this->sqlOrder === '') { + $this->sqlOrder = ' ORDER BY '.$this->db->escapeIdentifier($column).' '.$order; + } + else { + $this->sqlOrder .= ', '.$this->db->escapeIdentifier($column).' '.$order; + } + + return $this; + } + + /** + * Ascending sort + * + * @access public + * @param string $column + * @return $this + */ + public function asc($column) + { + $this->orderBy($column, self::SORT_ASC); + return $this; + } + + /** + * Descending sort + * + * @access public + * @param string $column + * @return $this + */ + public function desc($column) + { + $this->orderBy($column, self::SORT_DESC); + return $this; + } + + /** + * Limit + * + * @access public + * @param integer $value + * @return $this + */ + public function limit($value) + { + if (! is_null($value)) { + $this->sqlLimit = ' LIMIT '.(int) $value; + } + + return $this; + } + + /** + * Offset + * + * @access public + * @param integer $value + * @return $this + */ + public function offset($value) + { + if (! is_null($value)) { + $this->sqlOffset = ' OFFSET '.(int) $value; + } + + return $this; + } + + /** + * Group by + * + * @access public + * @return $this + */ + public function groupBy() + { + $this->groupBy = func_get_args(); + return $this; + } + + /** + * Custom select + * + * @access public + * @param string $select + * @return $this + */ + public function select($select) + { + $this->sqlSelect = $select; + return $this; + } + + /** + * Define the columns for the select + * + * @access public + * @return $this + */ + public function columns() + { + $this->columns = func_get_args(); + return $this; + } + + /** + * Sum column + * + * @access public + * @param string $column + * @param mixed $value + * @return $this + */ + public function sumColumn($column, $value) + { + $this->sumColumns[$column] = $value; + return $this; + } + + /** + * Distinct + * + * @access public + * @return $this + */ + public function distinct() + { + $this->columns = func_get_args(); + $this->distinct = true; + return $this; + } + + /** + * Add callback to alter the resultset + * + * @access public + * @param Closure|array $callback + * @return $this + */ + public function callback($callback) + { + $this->callback = $callback; + return $this; + } + + /** + * Build a select query + * + * @access public + * @return string + */ + public function buildSelectQuery() + { + if (empty($this->sqlSelect)) { + $this->columns = $this->db->escapeIdentifierList($this->columns); + $this->sqlSelect = ($this->distinct ? 'DISTINCT ' : '').(empty($this->columns) ? '*' : implode(', ', $this->columns)); + } + + $this->groupBy = $this->db->escapeIdentifierList($this->groupBy); + + return trim(sprintf( + 'SELECT %s FROM %s %s %s %s %s %s %s', + $this->sqlSelect, + $this->db->escapeIdentifier($this->name), + implode(' ', $this->joins), + $this->conditionBuilder->build(), + empty($this->groupBy) ? '' : 'GROUP BY '.implode(', ', $this->groupBy), + $this->sqlOrder, + $this->sqlLimit, + $this->sqlOffset + )); + } + + /** + * Magic method for sql conditions + * + * @access public + * @param string $name + * @param array $arguments + * @return $this + */ + public function __call($name, array $arguments) + { + call_user_func_array(array($this->conditionBuilder, $name), $arguments); + return $this; + } +} diff --git a/vendor/fguillot/picodb/lib/PicoDb/UrlParser.php b/vendor/fguillot/picodb/lib/PicoDb/UrlParser.php new file mode 100644 index 00000000..d8fcaf00 --- /dev/null +++ b/vendor/fguillot/picodb/lib/PicoDb/UrlParser.php @@ -0,0 +1,93 @@ +url = getenv($environmentVariable); + } + + /** + * Get object instance + * + * @access public + * @param string $environmentVariable + * @return static + */ + public static function getInstance($environmentVariable = 'DATABASE_URL') + { + return new static($environmentVariable); + } + + /** + * Return true if the variable is defined + * + * @access public + * @return bool + */ + public function isEnvironmentVariableDefined() + { + return ! empty($this->url); + } + + /** + * Get settings from URL + * + * @access public + * @param string $url + * @return array + */ + public function getSettings($url = '') + { + $url = $url ?: $this->url; + $components = parse_url($url); + + if ($components === false) { + return array(); + } + + return array( + 'driver' => $this->getUrlComponent($components, 'scheme'), + 'username' => $this->getUrlComponent($components, 'user'), + 'password' => $this->getUrlComponent($components, 'pass'), + 'hostname' => $this->getUrlComponent($components, 'host'), + 'port' => $this->getUrlComponent($components, 'port'), + 'database' => ltrim($this->getUrlComponent($components, 'path'), '/'), + ); + } + + /** + * Get URL component + * + * @access private + * @param array $components + * @param string $component + * @return mixed|null + */ + private function getUrlComponent(array $components, $component) + { + return ! empty($components[$component]) ? $components[$component] : null; + } +} diff --git a/vendor/fguillot/simple-queue/LICENSE b/vendor/fguillot/simple-queue/LICENSE new file mode 100644 index 00000000..a19d63a3 --- /dev/null +++ b/vendor/fguillot/simple-queue/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Frédéric Guillot + +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. diff --git a/vendor/fguillot/simple-queue/src/Adapter/AmqpQueueAdapter.php b/vendor/fguillot/simple-queue/src/Adapter/AmqpQueueAdapter.php new file mode 100644 index 00000000..379dd9b8 --- /dev/null +++ b/vendor/fguillot/simple-queue/src/Adapter/AmqpQueueAdapter.php @@ -0,0 +1,138 @@ +channel = $channel; + $this->exchange = $exchange; + $this->queue = $queue; + } + + /** + * Send a job + * + * @access public + * @param Job $job + * @return $this + */ + public function push(Job $job) + { + $message = new AMQPMessage($job->serialize(), array('content_type' => 'text/plain')); + $this->channel->basic_publish($message, $this->exchange); + return $this; + } + + /** + * Schedule a job in the future + * + * @access public + * @param Job $job + * @param DateTime $dateTime + * @return $this + */ + public function schedule(Job $job, DateTime $dateTime) + { + $now = new DateTime(); + $when = clone($dateTime); + $delay = $when->getTimestamp() - $now->getTimestamp(); + + $message = new AMQPMessage($job->serialize(), array('delivery_mode' => 2)); + $message->set('application_headers', new AMQPTable(array('x-delay' => $delay))); + + $this->channel->basic_publish($message, $this->exchange); + return $this; + } + + /** + * Wait and get job from a queue + * + * @access public + * @return Job|null + */ + public function pull() + { + $message = null; + + $this->channel->basic_consume($this->queue, 'test', false, false, false, false, function ($msg) use (&$message) { + $message = $msg; + $message->delivery_info['channel']->basic_cancel($message->delivery_info['consumer_tag']); + }); + + while (count($this->channel->callbacks)) { + $this->channel->wait(); + } + + if ($message === null) { + return null; + } + + $job = new Job(); + $job->setId($message->get('delivery_tag')); + $job->unserialize($message->getBody()); + + return $job; + } + + /** + * Acknowledge a job + * + * @access public + * @param Job $job + * @return $this + */ + public function completed(Job $job) + { + $this->channel->basic_ack($job->getId()); + return $this; + } + + /** + * Mark a job as failed + * + * @access public + * @param Job $job + * @return $this + */ + public function failed(Job $job) + { + $this->channel->basic_nack($job->getId()); + return $this; + } +} diff --git a/vendor/fguillot/simple-queue/src/Adapter/AwsSqsQueueAdapter.php b/vendor/fguillot/simple-queue/src/Adapter/AwsSqsQueueAdapter.php new file mode 100644 index 00000000..01377317 --- /dev/null +++ b/vendor/fguillot/simple-queue/src/Adapter/AwsSqsQueueAdapter.php @@ -0,0 +1,150 @@ + + */ +class AwsSqsQueueAdapter implements QueueAdapterInterface +{ + /** + * @var string + */ + private $queueName; + + /** + * @var SqsClient + */ + private $sqsClient; + + /** + * @var string + */ + private $sqsUrl; + + /** + * @var array + */ + private $config; + + /** + * AwsSqsQueueAdapter constructor. + * + * @param string $queueName The name of the SQS queue + * @param SqsClient $sqsClient An SQS client + * @param array $config Array of config values + */ + public function __construct($queueName, SqsClient $sqsClient, $config = array()) + { + $this->queueName = $queueName; + $this->sqsClient = $sqsClient; + $this->sqsUrl = $this->sqsClient->getQueueUrl(array('QueueName' => $this->queueName))->get('QueueUrl'); + $this->config = $config; + } + + /** + * Send a job + * + * @access public + * @param Job $job + * @return $this + */ + public function push(Job $job) + { + $this->sqsClient->sendMessage(array( + 'QueueUrl' => $this->sqsUrl, + 'MessageBody' => $job->serialize() + )); + return $this; + } + + /** + * Schedule a job in the future + * + * @access public + * @param Job $job + * @param DateTime $dateTime + * @return $this + */ + public function schedule(Job $job, DateTime $dateTime) + { + $now = new DateTime(); + $when = clone($dateTime); + $delay = $when->getTimestamp() - $now->getTimestamp(); + + $this->sqsClient->sendMessage(array( + 'QueueUrl' => $this->sqsUrl, + 'MessageBody' => $job->serialize(), + 'VisibilityTimeout' => $delay + )); + + return $this; + } + + /** + * Wait and get job from a queue + * + * @access public + * @return Job|null + */ + public function pull() + { + $result = $this->sqsClient->receiveMessage(array( + 'QueueUrl' => $this->sqsUrl, + 'WaitTimeSeconds' => empty($this->config['LongPollingTime']) ? 0 : (int) $this->config['LongPollingTime'] + )); + + if ($result['Messages'] == null) { + return null; + } + + $resultMessage = array_pop($result['Messages']); + + $job = new Job(); + $job->setId($resultMessage['ReceiptHandle']); + $job->unserialize($resultMessage['Body']); + + return $job; + } + + /** + * Acknowledge a job + * + * @access public + * @param Job $job + * @return $this + */ + public function completed(Job $job) + { + $this->sqsClient->deleteMessage(array( + 'QueueUrl' => $this->sqsUrl, + 'ReceiptHandle' => $job->getId() + )); + return $this; + } + + /** + * Mark a job as failed + * + * @access public + * @param Job $job + * @return $this + */ + public function failed(Job $job) + { + $this->sqsClient->changeMessageVisibility(array( + 'QueueUrl' => $this->sqsUrl, + 'ReceiptHandle' => $job->getId(), + 'VisibilityTimeout' => 0 + )); + return $this; + } +} diff --git a/vendor/fguillot/simple-queue/src/Adapter/BeanstalkQueueAdapter.php b/vendor/fguillot/simple-queue/src/Adapter/BeanstalkQueueAdapter.php new file mode 100644 index 00000000..407f60e2 --- /dev/null +++ b/vendor/fguillot/simple-queue/src/Adapter/BeanstalkQueueAdapter.php @@ -0,0 +1,120 @@ +beanstalk = $beanstalk; + $this->queueName = $queueName; + } + + /** + * Send a job + * + * @access public + * @param Job $job + * @return $this + */ + public function push(Job $job) + { + $this->beanstalk->putInTube($this->queueName, $job->serialize()); + return $this; + } + + /** + * Schedule a job in the future + * + * @access public + * @param Job $job + * @param DateTime $dateTime + * @return $this + */ + public function schedule(Job $job, DateTime $dateTime) + { + $now = new DateTime(); + $when = clone($dateTime); + $delay = $when->getTimestamp() - $now->getTimestamp(); + + $this->beanstalk->putInTube($this->queueName, $job->serialize(), Pheanstalk::DEFAULT_PRIORITY, $delay); + return $this; + } + + /** + * Wait and get job from a queue + * + * @access public + * @return Job|null + */ + public function pull() + { + $beanstalkJob = $this->beanstalk->reserveFromTube($this->queueName); + + if ($beanstalkJob === false) { + return null; + } + + $job = new Job(); + $job->setId($beanstalkJob->getId()); + $job->unserialize($beanstalkJob->getData()); + + return $job; + } + + /** + * Acknowledge a job + * + * @access public + * @param Job $job + * @return $this + */ + public function completed(Job $job) + { + $beanstalkJob = new BeanstalkJob($job->getId(), $job->serialize()); + $this->beanstalk->delete($beanstalkJob); + return $this; + } + + /** + * Mark a job as failed + * + * @access public + * @param Job $job + * @return $this + */ + public function failed(Job $job) + { + $beanstalkJob = new BeanstalkJob($job->getId(), $job->serialize()); + $this->beanstalk->bury($beanstalkJob); + return $this; + } +} diff --git a/vendor/fguillot/simple-queue/src/Adapter/DisqueQueueAdapter.php b/vendor/fguillot/simple-queue/src/Adapter/DisqueQueueAdapter.php new file mode 100644 index 00000000..047658d7 --- /dev/null +++ b/vendor/fguillot/simple-queue/src/Adapter/DisqueQueueAdapter.php @@ -0,0 +1,109 @@ +disque = $disque; + $this->queueName = $queueName; + } + + /** + * Send a job + * + * @access public + * @param Job $job + * @return $this + */ + public function push(Job $job) + { + $this->disque->queue($this->queueName)->push(new DisqueJob($job->getBody())); + return $this; + } + + /** + * Schedule a job in the future + * + * @access public + * @param Job $job + * @param DateTime $dateTime + * @return $this + */ + public function schedule(Job $job, DateTime $dateTime) + { + $this->disque->queue($this->queueName)->schedule(new DisqueJob($job->serialize()), $dateTime); + return $this; + } + + /** + * Wait and get job from a queue + * + * @access public + * @return Job|null + */ + public function pull() + { + $disqueJob = $this->disque->queue($this->queueName)->pull(); + + if ($disqueJob === null) { + return null; + } + + return new Job($disqueJob->getBody(), $disqueJob->getId()); + } + + /** + * Acknowledge a job + * + * @access public + * @param Job $job + * @return $this + */ + public function completed(Job $job) + { + $this->disque->queue($this->queueName)->processed(new DisqueJob($job->getBody(), $job->getId())); + return $this; + } + + /** + * Mark a job as failed + * + * @access public + * @param Job $job + * @return $this + */ + public function failed(Job $job) + { + $this->disque->queue($this->queueName)->failed(new DisqueJob($job->getBody(), $job->getId())); + return $this; + } +} diff --git a/vendor/fguillot/simple-queue/src/Adapter/MemoryQueueAdapter.php b/vendor/fguillot/simple-queue/src/Adapter/MemoryQueueAdapter.php new file mode 100644 index 00000000..36375d5b --- /dev/null +++ b/vendor/fguillot/simple-queue/src/Adapter/MemoryQueueAdapter.php @@ -0,0 +1,100 @@ +queue = new SplQueue(); + } + + /** + * Send a job + * + * @access public + * @param Job $job + * @return $this + */ + public function push(Job $job) + { + $this->queue->enqueue($job->serialize()); + return $this; + } + + /** + * Schedule a job in the future + * + * @access public + * @param Job $job + * @param DateTime $dateTime + * @return bool + * @throws NotSupportedException + */ + public function schedule(Job $job, DateTime $dateTime) + { + throw new NotSupportedException('Job delay is not supported by MemoryQueue'); + } + + /** + * Wait and get job from a queue + * + * @access public + * @return Job|null + */ + public function pull() + { + try { + $job = new Job(); + $payload = $this->queue->dequeue(); + return $job->unserialize($payload); + } catch (Exception $e) { + return null; + } + } + + /** + * Acknowledge a job + * + * @access public + * @param Job $job + * @return $this + */ + public function completed(Job $job) + { + return $this; + } + + /** + * Mark a job as failed + * + * @access public + * @param Job $job + * @return $this + */ + public function failed(Job $job) + { + $this->queue->enqueue($job->serialize()); + return $this; + } +} diff --git a/vendor/fguillot/simple-queue/src/Exception/NotSupportedException.php b/vendor/fguillot/simple-queue/src/Exception/NotSupportedException.php new file mode 100644 index 00000000..36106659 --- /dev/null +++ b/vendor/fguillot/simple-queue/src/Exception/NotSupportedException.php @@ -0,0 +1,14 @@ +body = $body; + $this->id = $id; + } + + /** + * Unserialize a payload + * + * @param string $payload + * @return $this + */ + public function unserialize($payload) + { + $this->body = json_decode($payload, true); + return $this; + } + + /** + * Serialize the body + * + * @return string + */ + public function serialize() + { + return json_encode($this->body); + } + + /** + * Set body + * + * @param mixed $body + * @return Job + */ + public function setBody($body) + { + $this->body = $body; + return $this; + } + + /** + * Get body + * + * @return mixed + */ + public function getBody() + { + return $this->body; + } + + /** + * Set job ID + * + * @param mixed $jobId + * @return Job + */ + public function setId($jobId) + { + $this->id = $jobId; + return $this; + } + + /** + * Get job ID + * @return mixed + */ + public function getId() + { + return $this->id; + } + + /** + * Execute job + */ + public function execute() + { + } +} diff --git a/vendor/fguillot/simple-queue/src/Queue.php b/vendor/fguillot/simple-queue/src/Queue.php new file mode 100644 index 00000000..a88b55cb --- /dev/null +++ b/vendor/fguillot/simple-queue/src/Queue.php @@ -0,0 +1,92 @@ +queueAdapter = $queueAdapter; + } + + /** + * Send a job + * + * @access public + * @param Job $job + * @return $this + */ + public function push(Job $job) + { + $this->queueAdapter->push($job); + return $this; + } + + /** + * Schedule a job in the future + * + * @access public + * @param Job $job + * @param DateTime $dateTime + * @return $this + */ + public function schedule(Job $job, DateTime $dateTime) + { + $this->queueAdapter->schedule($job, $dateTime); + return $this; + } + + /** + * Wait and get job from a queue + * + * @access public + * @return Job|null + */ + public function pull() + { + return $this->queueAdapter->pull(); + } + + /** + * Acknowledge a job + * + * @access public + * @param Job $job + * @return $this + */ + public function completed(Job $job) + { + $this->queueAdapter->completed($job); + return $this; + } + + /** + * Mark a job as failed + * + * @access public + * @param Job $job + * @return $this + */ + public function failed(Job $job) + { + $this->queueAdapter->failed($job); + return $this; + } +} diff --git a/vendor/fguillot/simple-queue/src/QueueAdapterInterface.php b/vendor/fguillot/simple-queue/src/QueueAdapterInterface.php new file mode 100644 index 00000000..9bda3070 --- /dev/null +++ b/vendor/fguillot/simple-queue/src/QueueAdapterInterface.php @@ -0,0 +1,58 @@ +data = $data; + $this->validators = $validators; + } + + public function execute() + { + $result = true; + + foreach ($this->validators as $validator) { + if (! $validator->execute($this->data)) { + $this->addError($validator->getField(), $validator->getErrorMessage()); + $result = false; + } + } + + return $result; + } + + public function addError($field, $message) + { + if (! isset($this->errors[$field])) { + $this->errors[$field] = array(); + } + + $this->errors[$field][] = $message; + } + + public function getErrors() + { + return $this->errors; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Alpha.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Alpha.php new file mode 100644 index 00000000..c29ba481 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Alpha.php @@ -0,0 +1,15 @@ +isFieldNotEmpty($data)) { + return ctype_alpha($data[$this->field]); + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/AlphaNumeric.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/AlphaNumeric.php new file mode 100644 index 00000000..8d5000b4 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/AlphaNumeric.php @@ -0,0 +1,15 @@ +isFieldNotEmpty($data)) { + return ctype_alnum($data[$this->field]); + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Base.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Base.php new file mode 100644 index 00000000..8157ae50 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Base.php @@ -0,0 +1,37 @@ +field = $field; + $this->error_message = $error_message; + } + + public function getErrorMessage() + { + return $this->error_message; + } + + public function getField() + { + if (is_array($this->field)) { + return $this->field[0]; + } + + return $this->field; + } + + public function isFieldNotEmpty(array $data) + { + return isset($data[$this->field]) && $data[$this->field] !== ''; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php new file mode 100644 index 00000000..4ec4b7fd --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Date.php @@ -0,0 +1,45 @@ +formats = $formats; + } + + public function execute(array $data) + { + if ($this->isFieldNotEmpty($data)) { + foreach ($this->formats as $format) { + if ($this->isValidDate($data[$this->field], $format)) { + return true; + } + } + + return false; + } + + return true; + } + + public function isValidDate($value, $format) + { + $date = DateTime::createFromFormat($format, $value); + + if ($date !== false) { + $errors = DateTime::getLastErrors(); + if ($errors['error_count'] === 0 && $errors['warning_count'] === 0) { + return $date->getTimestamp() > 0; + } + } + + return false; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php new file mode 100644 index 00000000..f3977042 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Email.php @@ -0,0 +1,67 @@ +isFieldNotEmpty($data)) { + + // I use the same validation method as Firefox + // http://hg.mozilla.org/mozilla-central/file/cf5da681d577/content/html/content/src/nsHTMLInputElement.cpp#l3967 + + $value = $data[$this->field]; + $length = strlen($value); + + // If the email address begins with a '@' or ends with a '.', + // we know it's invalid. + if ($value[0] === '@' || $value[$length - 1] === '.') { + + return false; + } + + // Check the username + for ($i = 0; $i < $length && $value[$i] !== '@'; ++$i) { + + $c = $value[$i]; + + if (! (ctype_alnum($c) || $c === '.' || $c === '!' || $c === '#' || $c === '$' || + $c === '%' || $c === '&' || $c === '\'' || $c === '*' || $c === '+' || + $c === '-' || $c === '/' || $c === '=' || $c === '?' || $c === '^' || + $c === '_' || $c === '`' || $c === '{' || $c === '|' || $c === '}' || + $c === '~')) { + + return false; + } + } + + // There is no domain name (or it's one-character long), + // that's not a valid email address. + if (++$i >= $length) return false; + if (($i + 1) === $length) return false; + + // The domain name can't begin with a dot. + if ($value[$i] === '.') return false; + + // Parsing the domain name. + for (; $i < $length; ++$i) { + + $c = $value[$i]; + + if ($c === '.') { + + // A dot can't follow a dot. + if ($value[$i - 1] === '.') return false; + } + elseif (! (ctype_alnum($c) || $c === '-')) { + + // The domain characters have to be in this list to be valid. + return false; + } + } + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php new file mode 100644 index 00000000..6b69dd80 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Equals.php @@ -0,0 +1,27 @@ +field2 = $field2; + } + + public function execute(array $data) + { + if ($this->isFieldNotEmpty($data)) { + if (! isset($data[$this->field2])) { + return false; + } + + return $data[$this->field] === $data[$this->field2]; + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php new file mode 100644 index 00000000..1998e673 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Exists.php @@ -0,0 +1,38 @@ +pdo = $pdo; + $this->table = $table; + $this->key = $key; + } + + + public function execute(array $data) + { + if (! $this->isFieldNotEmpty($data)) { + return true; + } + + if ($this->key === '') { + $this->key = $this->field; + } + + $rq = $this->pdo->prepare('SELECT 1 FROM '.$this->table.' WHERE '.$this->key.'=?'); + $rq->execute(array($data[$this->field])); + + return $rq->fetchColumn() == 1; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php new file mode 100644 index 00000000..6e560319 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/GreaterThan.php @@ -0,0 +1,23 @@ +min = $min; + } + + public function execute(array $data) + { + if ($this->isFieldNotEmpty($data)) { + return $data[$this->field] > $this->min; + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php new file mode 100644 index 00000000..f2f8c134 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/InArray.php @@ -0,0 +1,23 @@ +array = $array; + } + + public function execute(array $data) + { + if ($this->isFieldNotEmpty($data)) { + return in_array($data[$this->field], $this->array); + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php new file mode 100644 index 00000000..5afdc1e0 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Integer.php @@ -0,0 +1,25 @@ +isFieldNotEmpty($data)) { + if (is_string($data[$this->field])) { + + if ($data[$this->field][0] === '-') { + return ctype_digit(substr($data[$this->field], 1)); + } + + return ctype_digit($data[$this->field]); + } + else { + return is_int($data[$this->field]); + } + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Ip.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Ip.php new file mode 100644 index 00000000..754f4f3e --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Ip.php @@ -0,0 +1,15 @@ +isFieldNotEmpty($data)) { + return filter_var($data[$this->field], FILTER_VALIDATE_IP) !== false; + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Length.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Length.php new file mode 100644 index 00000000..7ef241c4 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Length.php @@ -0,0 +1,26 @@ +min = $min; + $this->max = $max; + } + + public function execute(array $data) + { + if ($this->isFieldNotEmpty($data)) { + $length = mb_strlen($data[$this->field], 'UTF-8'); + return $length >= $this->min && $length <= $this->max; + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php new file mode 100644 index 00000000..6c4e7771 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MaxLength.php @@ -0,0 +1,24 @@ +max = $max; + } + + public function execute(array $data) + { + if ($this->isFieldNotEmpty($data)) { + $length = mb_strlen($data[$this->field], 'UTF-8'); + return $length <= $this->max; + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php new file mode 100644 index 00000000..0ac4217a --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/MinLength.php @@ -0,0 +1,24 @@ +min = $min; + } + + public function execute(array $data) + { + if ($this->isFieldNotEmpty($data)) { + $length = mb_strlen($data[$this->field], 'UTF-8'); + return $length >= $this->min; + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEmpty.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEmpty.php new file mode 100644 index 00000000..bbb14b5b --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEmpty.php @@ -0,0 +1,15 @@ +field, $data)) { + return $data[$this->field] !== null && $data[$this->field] !== ''; + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php new file mode 100644 index 00000000..d1d949ea --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotEquals.php @@ -0,0 +1,28 @@ +field2 = $field2; + } + + public function execute(array $data) + { + if ($this->isFieldNotEmpty($data)) { + + if (! isset($data[$this->field2])) { + return true; + } + + return $data[$this->field] !== $data[$this->field2]; + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php new file mode 100644 index 00000000..98974c9c --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/NotInArray.php @@ -0,0 +1,15 @@ +isFieldNotEmpty($data)) { + return ! in_array($data[$this->field], $this->array); + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php new file mode 100644 index 00000000..31226866 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Numeric.php @@ -0,0 +1,15 @@ +isFieldNotEmpty($data)) { + return is_numeric($data[$this->field]); + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php new file mode 100644 index 00000000..065b2b9d --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Range.php @@ -0,0 +1,33 @@ +min = $min; + $this->max = $max; + } + + public function execute(array $data) + { + if ($this->isFieldNotEmpty($data)) { + + if (! is_numeric($data[$this->field])) { + return false; + } + + if ($data[$this->field] < $this->min || $data[$this->field] > $this->max) { + return false; + } + } + + return true; + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php new file mode 100644 index 00000000..f5e65616 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Required.php @@ -0,0 +1,11 @@ +isFieldNotEmpty($data); + } +} diff --git a/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php new file mode 100644 index 00000000..00caeb54 --- /dev/null +++ b/vendor/fguillot/simple-validator/src/SimpleValidator/Validators/Unique.php @@ -0,0 +1,48 @@ +pdo = $pdo; + $this->primary_key = $primary_key; + $this->table = $table; + } + + public function execute(array $data) + { + if ($this->isFieldNotEmpty($data)) { + if (! isset($data[$this->primary_key])) { + $rq = $this->pdo->prepare('SELECT 1 FROM '.$this->table.' WHERE '.$this->field.'=?'); + $rq->execute(array($data[$this->field])); + } + else { + + $rq = $this->pdo->prepare( + 'SELECT 1 FROM '.$this->table.' + WHERE '.$this->field.'=? AND '.$this->primary_key.' != ?' + ); + + $rq->execute(array($data[$this->field], $data[$this->primary_key])); + } + + $result = $rq->fetchColumn(); + + if ($result == 1) { // Postgresql returns an integer but other database returns a string '1' + return false; + } + } + + return true; + } +} diff --git a/vendor/fguillot/simpleLogger/LICENSE b/vendor/fguillot/simpleLogger/LICENSE new file mode 100644 index 00000000..6a362bc1 --- /dev/null +++ b/vendor/fguillot/simpleLogger/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2015 Frederic Guillot + +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. diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/Base.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/Base.php new file mode 100644 index 00000000..c662a1a3 --- /dev/null +++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/Base.php @@ -0,0 +1,89 @@ +level = $level; + } + + /** + * Get minimum log level + * + * @access public + * @return string + */ + public function getLevel() + { + return $this->level; + } + + /** + * Dump to log a variable (by example an array) + * + * @param mixed $variable + */ + public function dump($variable) + { + $this->log(LogLevel::DEBUG, var_export($variable, true)); + } + + /** + * Interpolates context values into the message placeholders. + * + * @access protected + * @param string $message + * @param array $context + * @return string + */ + protected function interpolate($message, array $context = array()) + { + // build a replacement array with braces around the context keys + $replace = array(); + + foreach ($context as $key => $val) { + $replace['{' . $key . '}'] = $val; + } + + // interpolate replacement values into the message and return + return strtr($message, $replace); + } + + /** + * Format log message + * + * @param mixed $level + * @param string $message + * @param array $context + * @return string + */ + protected function formatMessage($level, $message, array $context = array()) + { + return '['.date('Y-m-d H:i:s').'] ['.$level.'] '.$this->interpolate($message, $context).PHP_EOL; + } +} diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/File.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/File.php new file mode 100644 index 00000000..be3bfa85 --- /dev/null +++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/File.php @@ -0,0 +1,48 @@ +filename = $filename; + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + */ + public function log($level, $message, array $context = array()) + { + $line = $this->formatMessage($level, $message, $context); + + if (file_put_contents($this->filename, $line, FILE_APPEND | LOCK_EX) === false) { + throw new RuntimeException('Unable to write to the log file.'); + } + } +} diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/Logger.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/Logger.php new file mode 100644 index 00000000..dc340cde --- /dev/null +++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/Logger.php @@ -0,0 +1,94 @@ +loggers[] = $logger; + } + + /** + * Proxy method to the real loggers + * + * @param mixed $level + * @param string $message + * @param array $context + * @return null + */ + public function log($level, $message, array $context = array()) + { + foreach ($this->loggers as $logger) { + if ($this->getLevelPriority($level) >= $this->getLevelPriority($logger->getLevel())) { + $logger->log($level, $message, $context); + } + } + } + + /** + * Dump variables for debugging + * + * @param mixed $variable + */ + public function dump($variable) + { + foreach ($this->loggers as $logger) { + if ($this->getLevelPriority(LogLevel::DEBUG) >= $this->getLevelPriority($logger->getLevel())) { + $logger->dump($variable); + } + } + } +} diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/Stderr.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/Stderr.php new file mode 100644 index 00000000..2573177e --- /dev/null +++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/Stderr.php @@ -0,0 +1,25 @@ +formatMessage($level, $message, $context), FILE_APPEND); + } +} diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/Stdout.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/Stdout.php new file mode 100644 index 00000000..82d181b2 --- /dev/null +++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/Stdout.php @@ -0,0 +1,25 @@ +formatMessage($level, $message, $context), FILE_APPEND); + } +} diff --git a/vendor/fguillot/simpleLogger/src/SimpleLogger/Syslog.php b/vendor/fguillot/simpleLogger/src/SimpleLogger/Syslog.php new file mode 100644 index 00000000..c4e26a7a --- /dev/null +++ b/vendor/fguillot/simpleLogger/src/SimpleLogger/Syslog.php @@ -0,0 +1,72 @@ +getSyslogPriority($level); + $syslogMessage = $this->interpolate($message, $context); + + syslog($syslogPriority, $syslogMessage); + } +} -- cgit v1.2.3