From f3b52f1dd9441a1fbfd4b50ee60766fae00a0d41 Mon Sep 17 00:00:00 2001 From: Skylar Date: Mon, 16 May 2016 15:43:49 -0600 Subject: [PATCH] First commit --- composer.json | 13 + composer.lock | 74 ++ database.php | 12 + dieifnotloggedin.php | 7 + getitem.php | 14 + login.php | 24 + nbproject/project.properties | 7 + nbproject/project.xml | 9 + readfrom.php | 18 + required.php | 85 ++ search.php | 24 + vendor/autoload.php | 7 + vendor/catfan/medoo/.gitattributes | 22 + vendor/catfan/medoo/.gitignore | 163 ++++ vendor/catfan/medoo/LICENSE | 22 + vendor/catfan/medoo/README.md | 77 ++ vendor/catfan/medoo/composer.json | 26 + vendor/catfan/medoo/medoo.php | 989 ++++++++++++++++++++++++ vendor/catfan/medoo/src/medoo-logo.png | Bin 0 -> 37776 bytes vendor/composer/ClassLoader.php | 413 ++++++++++ vendor/composer/LICENSE | 21 + vendor/composer/autoload_classmap.php | 9 + vendor/composer/autoload_files.php | 10 + vendor/composer/autoload_namespaces.php | 9 + vendor/composer/autoload_psr4.php | 9 + vendor/composer/autoload_real.php | 70 ++ vendor/composer/autoload_static.php | 19 + vendor/composer/installed.json | 59 ++ 28 files changed, 2212 insertions(+) create mode 100644 composer.json create mode 100644 composer.lock create mode 100644 database.php create mode 100644 dieifnotloggedin.php create mode 100644 getitem.php create mode 100644 login.php create mode 100644 nbproject/project.properties create mode 100644 nbproject/project.xml create mode 100644 readfrom.php create mode 100644 required.php create mode 100644 search.php create mode 100644 vendor/autoload.php create mode 100644 vendor/catfan/medoo/.gitattributes create mode 100644 vendor/catfan/medoo/.gitignore create mode 100644 vendor/catfan/medoo/LICENSE create mode 100644 vendor/catfan/medoo/README.md create mode 100644 vendor/catfan/medoo/composer.json create mode 100644 vendor/catfan/medoo/medoo.php create mode 100644 vendor/catfan/medoo/src/medoo-logo.png create mode 100644 vendor/composer/ClassLoader.php create mode 100644 vendor/composer/LICENSE create mode 100644 vendor/composer/autoload_classmap.php create mode 100644 vendor/composer/autoload_files.php create mode 100644 vendor/composer/autoload_namespaces.php create mode 100644 vendor/composer/autoload_psr4.php create mode 100644 vendor/composer/autoload_real.php create mode 100644 vendor/composer/autoload_static.php create mode 100644 vendor/composer/installed.json diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..dfcbc4c --- /dev/null +++ b/composer.json @@ -0,0 +1,13 @@ +{ + "name": "vendor/snipe-i-t-mobile-a-p-i", + "description": "Description of project SnipeITMobileAPI.", + "authors": [ + { + "name": "skylar", + "email": "your@email.here" + } + ], + "require": { + "catfan/medoo": "^1.0" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..e73a59f --- /dev/null +++ b/composer.lock @@ -0,0 +1,74 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "bad8bf714cccc6e8c31f7f9c70bfb3d4", + "content-hash": "068ade3844dbf939c7d10fc2cb39436d", + "packages": [ + { + "name": "catfan/medoo", + "version": "v1.0.2", + "source": { + "type": "git", + "url": "https://github.com/catfan/Medoo.git", + "reference": "342e2d6a3bcf4adcac58e67593d63547139ab1ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/catfan/Medoo/zipball/342e2d6a3bcf4adcac58e67593d63547139ab1ac", + "reference": "342e2d6a3bcf4adcac58e67593d63547139ab1ac", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "php": ">=5.1" + }, + "suggest": { + "ext-pdo_dblib": "For MSSQL or Sybase databases on Linux/UNIX platform", + "ext-pdo_mysql": "For MySQL or MariaDB databases", + "ext-pdo_oci": "For Oracle databases", + "ext-pdo_pqsql": "For PostgreSQL databases", + "ext-pdo_sqlite": "For SQLite databases", + "ext-pdo_sqlsrv": "For MSSQL databases on Windows platform" + }, + "type": "framework", + "autoload": { + "files": [ + "medoo.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Angel Lai", + "email": "angel@catfan.me" + } + ], + "description": "The Lightest PHP database framework to accelerate development", + "homepage": "http://medoo.in", + "keywords": [ + "database", + "lightweight", + "mssql", + "mysql", + "php framework", + "sql", + "sqlite" + ], + "time": "2016-02-14 16:03:42" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/database.php b/database.php new file mode 100644 index 0000000..5a0619c --- /dev/null +++ b/database.php @@ -0,0 +1,12 @@ + 'mysql', + 'database_name' => 'snipeit', + 'server' => 'localhost', + 'username' => 'snipeit', + 'password' => 'snipeit', + 'charset' => 'utf8' + ] +); diff --git a/dieifnotloggedin.php b/dieifnotloggedin.php new file mode 100644 index 0000000..b68e9f1 --- /dev/null +++ b/dieifnotloggedin.php @@ -0,0 +1,7 @@ +select($from, '*', ['id' => $id])[0]; +die(json_encode(['status' => 'OK', 'results' => $results])); \ No newline at end of file diff --git a/login.php b/login.php new file mode 100644 index 0000000..6f56b47 --- /dev/null +++ b/login.php @@ -0,0 +1,24 @@ + + + org.netbeans.modules.php.project + + + SnipeITMobileAPI + + + diff --git a/readfrom.php b/readfrom.php new file mode 100644 index 0000000..5d25900 --- /dev/null +++ b/readfrom.php @@ -0,0 +1,18 @@ +has('users', ['username' => $username]); +} + +/** + * Check if a user exists in the database by email. + * @param String $username + */ +function email_exists($email) { + global $database; + return $database->has('users', ['email' => $email]); +} + +/** + * Checks the given credentials against the database. + * Can use either email or username for identity. + * @param string $username + * @param string $password + * @return boolean True if OK, else false + */ +function authenticate_user($username, $password) { + global $database; + $qf = 'username'; + if (!username_exists($username)) { + if (!email_exists($username)) { + return false; + } else { + $qf = 'email'; + } + } + $hash = $database->select('users', ['password'], [$qf => $username])[0]['password']; + return (password_verify($password, $hash)); +} + +/** + * Checks if a string or whatever is empty. + * @param $str The thingy to check + * @return boolean True if it's empty or whatever. + */ +function is_empty($str) { + return (!isset($str) || $str == '' || $str == null); +} + +function sendOK($message = "", $die = true) { + if (!is_empty($message) && JSON) { + echo '{ "status": "OK", "message": "' . $message . '" }'; + } elseif (is_empty($message) && JSON) { + echo '{ "status": "OK" }'; + } elseif (!is_empty($message) && !JSON) { + echo "OK:$message"; + } else { + echo "OK"; + } + if ($die) { + die(); + } +} + +function sendError($error, $die = true) { + if (JSON) { + echo '{ "status": "ERROR", "message": "' . $error . '" }'; + } else { + echo "Error: $error"; + } + if ($die) { + die(); + } +} diff --git a/search.php b/search.php new file mode 100644 index 0000000..af9da28 --- /dev/null +++ b/search.php @@ -0,0 +1,24 @@ + 'OK', 'results' => []])); +} + +$results; +if ($from == 'assets') { + $results = $database->select($from, '*', ['OR' => ['name[~]' => $q, 'asset_tag[~]' => $q, 'serial[~]' => $q, 'order_number[~]' => $q]]); +} else { + $results = $database->select($from, '*', ['OR' => ['name[~]' => $q, 'order_number[~]' => $q]]); +} + +//var_dump($database->error()); +//var_dump($results); + +die(json_encode(['status' => 'OK', 'results' => $results])); \ No newline at end of file diff --git a/vendor/autoload.php b/vendor/autoload.php new file mode 100644 index 0000000..0d8e012 --- /dev/null +++ b/vendor/autoload.php @@ -0,0 +1,7 @@ + The Lightest PHP database framework to accelerate development + +## Main Features + +* **Lightweight** - 20KB around with only one file. + +* **Easy** - Extremely easy to learn and use, friendly construction. + +* **Powerful** - Support various common and complex SQL queries. + +* **Compatible** - Support various SQL database, including MySQL, MSSQL, SQLite, MariaDB, Sybase, Oracle, PostgreSQL and more. + +* **Security** - Prevent SQL injection. + +* **Free** - Under MIT license, you can use it anywhere if you want. + +## Get Started + +### Install via composer + +Add Medoo to composer.json configuration file. +``` +$ composer require catfan/Medoo +``` + +And update the composer +``` +$ composer update +``` + +```php +// If you installed via composer, just use this code to requrie autoloader on the top of your projects. +require 'vendor/autoload.php'; + +// Or if you just download the medoo.php into directory, require it with the correct path. +require_once 'medoo.php'; + +// Initialize +$database = new medoo([ + 'database_type' => 'mysql', + 'database_name' => 'name', + 'server' => 'localhost', + 'username' => 'your_username', + 'password' => 'your_password', + 'charset' => 'utf8' +]); + +// Enjoy +$database->insert('account', [ + 'user_name' => 'foo', + 'email' => 'foo@bar.com', + 'age' => 25, + 'lang' => ['en', 'fr', 'jp', 'cn'] +]); +``` + +## Contribution Guides + +For most of time, Medoo is using develop branch for adding feature and fixing bug, and the branch will be merged into master branch while releasing a public version. For contribution, submit your code to the develop branch, and start a pull request into it. + +On develop branch, each commits are started with `[fix]`, `[feature]` or `[update]` tag to indicate the change. + +Keep it simple and keep it clear. + +## License + +Medoo is under the MIT license. + +## Links + +* Official website: [http://medoo.in](http://medoo.in) + +* Documentation: [http://medoo.in/doc](http://medoo.in/doc) \ No newline at end of file diff --git a/vendor/catfan/medoo/composer.json b/vendor/catfan/medoo/composer.json new file mode 100644 index 0000000..b9569a8 --- /dev/null +++ b/vendor/catfan/medoo/composer.json @@ -0,0 +1,26 @@ +{ + "name": "catfan/medoo", + "type": "framework", + "description": "The Lightest PHP database framework to accelerate development", + "keywords": ["database", "lightweight", "PHP framework", "SQL", "MySQL", "MSSQL", "SQLite"], + "homepage": "http://medoo.in", + "license": "MIT", + "authors": [ + {"name": "Angel Lai", "email": "angel@catfan.me"} + ], + "require": { + "php": ">=5.1", + "ext-pdo": "*" + }, + "suggest": { + "ext-pdo_mysql": "For MySQL or MariaDB databases", + "ext-pdo_sqlsrv": "For MSSQL databases on Windows platform", + "ext-pdo_dblib": "For MSSQL or Sybase databases on Linux/UNIX platform", + "ext-pdo_oci": "For Oracle databases", + "ext-pdo_pqsql": "For PostgreSQL databases", + "ext-pdo_sqlite": "For SQLite databases" + }, + "autoload": { + "files": ["medoo.php"] + } +} \ No newline at end of file diff --git a/vendor/catfan/medoo/medoo.php b/vendor/catfan/medoo/medoo.php new file mode 100644 index 0000000..dc2c195 --- /dev/null +++ b/vendor/catfan/medoo/medoo.php @@ -0,0 +1,989 @@ + $value) + { + $this->$option = $value; + } + } + else + { + return false; + } + + if ( + isset($this->port) && + is_int($this->port * 1) + ) + { + $port = $this->port; + } + + $type = strtolower($this->database_type); + $is_port = isset($port); + + if (isset($options[ 'prefix' ])) + { + $this->prefix = $options[ 'prefix' ]; + } + + switch ($type) + { + case 'mariadb': + $type = 'mysql'; + + case 'mysql': + if ($this->socket) + { + $dsn = $type . ':unix_socket=' . $this->socket . ';dbname=' . $this->database_name; + } + else + { + $dsn = $type . ':host=' . $this->server . ($is_port ? ';port=' . $port : '') . ';dbname=' . $this->database_name; + } + + // Make MySQL using standard quoted identifier + $commands[] = 'SET SQL_MODE=ANSI_QUOTES'; + break; + + case 'pgsql': + $dsn = $type . ':host=' . $this->server . ($is_port ? ';port=' . $port : '') . ';dbname=' . $this->database_name; + break; + + case 'sybase': + $dsn = 'dblib:host=' . $this->server . ($is_port ? ':' . $port : '') . ';dbname=' . $this->database_name; + break; + + case 'oracle': + $dbname = $this->server ? + '//' . $this->server . ($is_port ? ':' . $port : ':1521') . '/' . $this->database_name : + $this->database_name; + + $dsn = 'oci:dbname=' . $dbname . ($this->charset ? ';charset=' . $this->charset : ''); + break; + + case 'mssql': + $dsn = strstr(PHP_OS, 'WIN') ? + 'sqlsrv:server=' . $this->server . ($is_port ? ',' . $port : '') . ';database=' . $this->database_name : + 'dblib:host=' . $this->server . ($is_port ? ':' . $port : '') . ';dbname=' . $this->database_name; + + // Keep MSSQL QUOTED_IDENTIFIER is ON for standard quoting + $commands[] = 'SET QUOTED_IDENTIFIER ON'; + break; + + case 'sqlite': + $dsn = $type . ':' . $this->database_file; + $this->username = null; + $this->password = null; + break; + } + + if ( + in_array($type, explode(' ', 'mariadb mysql pgsql sybase mssql')) && + $this->charset + ) + { + $commands[] = "SET NAMES '" . $this->charset . "'"; + } + + $this->pdo = new PDO( + $dsn, + $this->username, + $this->password, + $this->option + ); + + foreach ($commands as $value) + { + $this->pdo->exec($value); + } + } + catch (PDOException $e) { + throw new Exception($e->getMessage()); + } + } + + public function query($query) + { + if ($this->debug_mode) + { + echo $query; + + $this->debug_mode = false; + + return false; + } + + array_push($this->logs, $query); + + return $this->pdo->query($query); + } + + public function exec($query) + { + if ($this->debug_mode) + { + echo $query; + + $this->debug_mode = false; + + return false; + } + + array_push($this->logs, $query); + + return $this->pdo->exec($query); + } + + public function quote($string) + { + return $this->pdo->quote($string); + } + + protected function column_quote($string) + { + return '"' . str_replace('.', '"."', preg_replace('/(^#|\(JSON\)\s*)/', '', $string)) . '"'; + } + + protected function column_push($columns) + { + if ($columns == '*') + { + return $columns; + } + + if (is_string($columns)) + { + $columns = array($columns); + } + + $stack = array(); + + foreach ($columns as $key => $value) + { + preg_match('/([a-zA-Z0-9_\-\.]*)\s*\(([a-zA-Z0-9_\-]*)\)/i', $value, $match); + + if (isset($match[ 1 ], $match[ 2 ])) + { + array_push($stack, $this->column_quote( $match[ 1 ] ) . ' AS ' . $this->column_quote( $match[ 2 ] )); + } + else + { + array_push($stack, $this->column_quote( $value )); + } + } + + return implode($stack, ','); + } + + protected function array_quote($array) + { + $temp = array(); + + foreach ($array as $value) + { + $temp[] = is_int($value) ? $value : $this->pdo->quote($value); + } + + return implode($temp, ','); + } + + protected function inner_conjunct($data, $conjunctor, $outer_conjunctor) + { + $haystack = array(); + + foreach ($data as $value) + { + $haystack[] = '(' . $this->data_implode($value, $conjunctor) . ')'; + } + + return implode($outer_conjunctor . ' ', $haystack); + } + + protected function fn_quote($column, $string) + { + return (strpos($column, '#') === 0 && preg_match('/^[A-Z0-9\_]*\([^)]*\)$/', $string)) ? + + $string : + + $this->quote($string); + } + + protected function data_implode($data, $conjunctor, $outer_conjunctor = null) + { + $wheres = array(); + + foreach ($data as $key => $value) + { + $type = gettype($value); + + if ( + preg_match("/^(AND|OR)(\s+#.*)?$/i", $key, $relation_match) && + $type == 'array' + ) + { + $wheres[] = 0 !== count(array_diff_key($value, array_keys(array_keys($value)))) ? + '(' . $this->data_implode($value, ' ' . $relation_match[ 1 ]) . ')' : + '(' . $this->inner_conjunct($value, ' ' . $relation_match[ 1 ], $conjunctor) . ')'; + } + else + { + preg_match('/(#?)([\w\.\-]+)(\[(\>|\>\=|\<|\<\=|\!|\<\>|\>\<|\!?~)\])?/i', $key, $match); + $column = $this->column_quote($match[ 2 ]); + + if (isset($match[ 4 ])) + { + $operator = $match[ 4 ]; + + if ($operator == '!') + { + switch ($type) + { + case 'NULL': + $wheres[] = $column . ' IS NOT NULL'; + break; + + case 'array': + $wheres[] = $column . ' NOT IN (' . $this->array_quote($value) . ')'; + break; + + case 'integer': + case 'double': + $wheres[] = $column . ' != ' . $value; + break; + + case 'boolean': + $wheres[] = $column . ' != ' . ($value ? '1' : '0'); + break; + + case 'string': + $wheres[] = $column . ' != ' . $this->fn_quote($key, $value); + break; + } + } + + if ($operator == '<>' || $operator == '><') + { + if ($type == 'array') + { + if ($operator == '><') + { + $column .= ' NOT'; + } + + if (is_numeric($value[ 0 ]) && is_numeric($value[ 1 ])) + { + $wheres[] = '(' . $column . ' BETWEEN ' . $value[ 0 ] . ' AND ' . $value[ 1 ] . ')'; + } + else + { + $wheres[] = '(' . $column . ' BETWEEN ' . $this->quote($value[ 0 ]) . ' AND ' . $this->quote($value[ 1 ]) . ')'; + } + } + } + + if ($operator == '~' || $operator == '!~') + { + if ($type != 'array') + { + $value = array($value); + } + + $like_clauses = array(); + + foreach ($value as $item) + { + $item = strval($item); + $suffix = mb_substr($item, -1, 1); + + if ($suffix === '_') + { + $item = substr_replace($item, '%', -1); + } + elseif ($suffix === '%') + { + $item = '%' . substr_replace($item, '', -1, 1); + } + elseif (preg_match('/^(?!%).+(?fn_quote($key, $item); + } + + $wheres[] = implode(' OR ', $like_clauses); + } + + if (in_array($operator, array('>', '>=', '<', '<='))) + { + if (is_numeric($value)) + { + $wheres[] = $column . ' ' . $operator . ' ' . $value; + } + elseif (strpos($key, '#') === 0) + { + $wheres[] = $column . ' ' . $operator . ' ' . $this->fn_quote($key, $value); + } + else + { + $wheres[] = $column . ' ' . $operator . ' ' . $this->quote($value); + } + } + } + else + { + switch ($type) + { + case 'NULL': + $wheres[] = $column . ' IS NULL'; + break; + + case 'array': + $wheres[] = $column . ' IN (' . $this->array_quote($value) . ')'; + break; + + case 'integer': + case 'double': + $wheres[] = $column . ' = ' . $value; + break; + + case 'boolean': + $wheres[] = $column . ' = ' . ($value ? '1' : '0'); + break; + + case 'string': + $wheres[] = $column . ' = ' . $this->fn_quote($key, $value); + break; + } + } + } + } + + return implode($conjunctor . ' ', $wheres); + } + + protected function where_clause($where) + { + $where_clause = ''; + + if (is_array($where)) + { + $where_keys = array_keys($where); + $where_AND = preg_grep("/^AND\s*#?$/i", $where_keys); + $where_OR = preg_grep("/^OR\s*#?$/i", $where_keys); + + $single_condition = array_diff_key($where, array_flip( + explode(' ', 'AND OR GROUP ORDER HAVING LIMIT LIKE MATCH') + )); + + if ($single_condition != array()) + { + $condition = $this->data_implode($single_condition, ''); + + if ($condition != '') + { + $where_clause = ' WHERE ' . $condition; + } + } + + if (!empty($where_AND)) + { + $value = array_values($where_AND); + $where_clause = ' WHERE ' . $this->data_implode($where[ $value[ 0 ] ], ' AND'); + } + + if (!empty($where_OR)) + { + $value = array_values($where_OR); + $where_clause = ' WHERE ' . $this->data_implode($where[ $value[ 0 ] ], ' OR'); + } + + if (isset($where[ 'MATCH' ])) + { + $MATCH = $where[ 'MATCH' ]; + + if (is_array($MATCH) && isset($MATCH[ 'columns' ], $MATCH[ 'keyword' ])) + { + $where_clause .= ($where_clause != '' ? ' AND ' : ' WHERE ') . ' MATCH ("' . str_replace('.', '"."', implode($MATCH[ 'columns' ], '", "')) . '") AGAINST (' . $this->quote($MATCH[ 'keyword' ]) . ')'; + } + } + + if (isset($where[ 'GROUP' ])) + { + $where_clause .= ' GROUP BY ' . $this->column_quote($where[ 'GROUP' ]); + + if (isset($where[ 'HAVING' ])) + { + $where_clause .= ' HAVING ' . $this->data_implode($where[ 'HAVING' ], ' AND'); + } + } + + if (isset($where[ 'ORDER' ])) + { + $rsort = '/(^[a-zA-Z0-9_\-\.]*)(\s*(DESC|ASC))?/'; + $ORDER = $where[ 'ORDER' ]; + + if (is_array($ORDER)) + { + if ( + isset($ORDER[ 1 ]) && + is_array($ORDER[ 1 ]) + ) + { + $where_clause .= ' ORDER BY FIELD(' . $this->column_quote($ORDER[ 0 ]) . ', ' . $this->array_quote($ORDER[ 1 ]) . ')'; + } + else + { + $stack = array(); + + foreach ($ORDER as $column) + { + preg_match($rsort, $column, $order_match); + + array_push($stack, '"' . str_replace('.', '"."', $order_match[ 1 ]) . '"' . (isset($order_match[ 3 ]) ? ' ' . $order_match[ 3 ] : '')); + } + + $where_clause .= ' ORDER BY ' . implode($stack, ','); + } + } + else + { + preg_match($rsort, $ORDER, $order_match); + + $where_clause .= ' ORDER BY "' . str_replace('.', '"."', $order_match[ 1 ]) . '"' . (isset($order_match[ 3 ]) ? ' ' . $order_match[ 3 ] : ''); + } + } + + if (isset($where[ 'LIMIT' ])) + { + $LIMIT = $where[ 'LIMIT' ]; + + if (is_numeric($LIMIT)) + { + $where_clause .= ' LIMIT ' . $LIMIT; + } + + if ( + is_array($LIMIT) && + is_numeric($LIMIT[ 0 ]) && + is_numeric($LIMIT[ 1 ]) + ) + { + if ($this->database_type === 'pgsql') + { + $where_clause .= ' OFFSET ' . $LIMIT[ 0 ] . ' LIMIT ' . $LIMIT[ 1 ]; + } + else + { + $where_clause .= ' LIMIT ' . $LIMIT[ 0 ] . ',' . $LIMIT[ 1 ]; + } + } + } + } + else + { + if ($where != null) + { + $where_clause .= ' ' . $where; + } + } + + return $where_clause; + } + + protected function select_context($table, $join, &$columns = null, $where = null, $column_fn = null) + { + $table = '"' . $this->prefix . $table . '"'; + $join_key = is_array($join) ? array_keys($join) : null; + + if ( + isset($join_key[ 0 ]) && + strpos($join_key[ 0 ], '[') === 0 + ) + { + $table_join = array(); + + $join_array = array( + '>' => 'LEFT', + '<' => 'RIGHT', + '<>' => 'FULL', + '><' => 'INNER' + ); + + foreach($join as $sub_table => $relation) + { + preg_match('/(\[(\<|\>|\>\<|\<\>)\])?([a-zA-Z0-9_\-]*)\s?(\(([a-zA-Z0-9_\-]*)\))?/', $sub_table, $match); + + if ($match[ 2 ] != '' && $match[ 3 ] != '') + { + if (is_string($relation)) + { + $relation = 'USING ("' . $relation . '")'; + } + + if (is_array($relation)) + { + // For ['column1', 'column2'] + if (isset($relation[ 0 ])) + { + $relation = 'USING ("' . implode($relation, '", "') . '")'; + } + else + { + $joins = array(); + + foreach ($relation as $key => $value) + { + $joins[] = $this->prefix . ( + strpos($key, '.') > 0 ? + // For ['tableB.column' => 'column'] + '"' . str_replace('.', '"."', $key) . '"' : + + // For ['column1' => 'column2'] + $table . '."' . $key . '"' + ) . + ' = ' . + '"' . (isset($match[ 5 ]) ? $match[ 5 ] : $match[ 3 ]) . '"."' . $value . '"'; + } + + $relation = 'ON ' . implode($joins, ' AND '); + } + } + + $table_join[] = $join_array[ $match[ 2 ] ] . ' JOIN "' . $this->prefix . $match[ 3 ] . '" ' . (isset($match[ 5 ]) ? 'AS "' . $match[ 5 ] . '" ' : '') . $relation; + } + } + + $table .= ' ' . implode($table_join, ' '); + } + else + { + if (is_null($columns)) + { + if (is_null($where)) + { + if ( + is_array($join) && + isset($column_fn) + ) + { + $where = $join; + $columns = null; + } + else + { + $where = null; + $columns = $join; + } + } + else + { + $where = $join; + $columns = null; + } + } + else + { + $where = $columns; + $columns = $join; + } + } + + if (isset($column_fn)) + { + if ($column_fn == 1) + { + $column = '1'; + + if (is_null($where)) + { + $where = $columns; + } + } + else + { + if (empty($columns)) + { + $columns = '*'; + $where = $join; + } + + $column = $column_fn . '(' . $this->column_push($columns) . ')'; + } + } + else + { + $column = $this->column_push($columns); + } + + return 'SELECT ' . $column . ' FROM ' . $table . $this->where_clause($where); + } + + public function select($table, $join, $columns = null, $where = null) + { + $query = $this->query($this->select_context($table, $join, $columns, $where)); + + return $query ? $query->fetchAll( + (is_string($columns) && $columns != '*') ? PDO::FETCH_COLUMN : PDO::FETCH_ASSOC + ) : false; + } + + public function insert($table, $datas) + { + $lastId = array(); + + // Check indexed or associative array + if (!isset($datas[ 0 ])) + { + $datas = array($datas); + } + + foreach ($datas as $data) + { + $values = array(); + $columns = array(); + + foreach ($data as $key => $value) + { + array_push($columns, $this->column_quote($key)); + + switch (gettype($value)) + { + case 'NULL': + $values[] = 'NULL'; + break; + + case 'array': + preg_match("/\(JSON\)\s*([\w]+)/i", $key, $column_match); + + $values[] = isset($column_match[ 0 ]) ? + $this->quote(json_encode($value)) : + $this->quote(serialize($value)); + break; + + case 'boolean': + $values[] = ($value ? '1' : '0'); + break; + + case 'integer': + case 'double': + case 'string': + $values[] = $this->fn_quote($key, $value); + break; + } + } + + $this->exec('INSERT INTO "' . $this->prefix . $table . '" (' . implode(', ', $columns) . ') VALUES (' . implode($values, ', ') . ')'); + + $lastId[] = $this->pdo->lastInsertId(); + } + + return count($lastId) > 1 ? $lastId : $lastId[ 0 ]; + } + + public function update($table, $data, $where = null) + { + $fields = array(); + + foreach ($data as $key => $value) + { + preg_match('/([\w]+)(\[(\+|\-|\*|\/)\])?/i', $key, $match); + + if (isset($match[ 3 ])) + { + if (is_numeric($value)) + { + $fields[] = $this->column_quote($match[ 1 ]) . ' = ' . $this->column_quote($match[ 1 ]) . ' ' . $match[ 3 ] . ' ' . $value; + } + } + else + { + $column = $this->column_quote($key); + + switch (gettype($value)) + { + case 'NULL': + $fields[] = $column . ' = NULL'; + break; + + case 'array': + preg_match("/\(JSON\)\s*([\w]+)/i", $key, $column_match); + + $fields[] = $column . ' = ' . $this->quote( + isset($column_match[ 0 ]) ? json_encode($value) : serialize($value) + ); + break; + + case 'boolean': + $fields[] = $column . ' = ' . ($value ? '1' : '0'); + break; + + case 'integer': + case 'double': + case 'string': + $fields[] = $column . ' = ' . $this->fn_quote($key, $value); + break; + } + } + } + + return $this->exec('UPDATE "' . $this->prefix . $table . '" SET ' . implode(', ', $fields) . $this->where_clause($where)); + } + + public function delete($table, $where) + { + return $this->exec('DELETE FROM "' . $this->prefix . $table . '"' . $this->where_clause($where)); + } + + public function replace($table, $columns, $search = null, $replace = null, $where = null) + { + if (is_array($columns)) + { + $replace_query = array(); + + foreach ($columns as $column => $replacements) + { + foreach ($replacements as $replace_search => $replace_replacement) + { + $replace_query[] = $column . ' = REPLACE(' . $this->column_quote($column) . ', ' . $this->quote($replace_search) . ', ' . $this->quote($replace_replacement) . ')'; + } + } + + $replace_query = implode(', ', $replace_query); + $where = $search; + } + else + { + if (is_array($search)) + { + $replace_query = array(); + + foreach ($search as $replace_search => $replace_replacement) + { + $replace_query[] = $columns . ' = REPLACE(' . $this->column_quote($columns) . ', ' . $this->quote($replace_search) . ', ' . $this->quote($replace_replacement) . ')'; + } + + $replace_query = implode(', ', $replace_query); + $where = $replace; + } + else + { + $replace_query = $columns . ' = REPLACE(' . $this->column_quote($columns) . ', ' . $this->quote($search) . ', ' . $this->quote($replace) . ')'; + } + } + + return $this->exec('UPDATE "' . $this->prefix . $table . '" SET ' . $replace_query . $this->where_clause($where)); + } + + public function get($table, $join = null, $column = null, $where = null) + { + $query = $this->query($this->select_context($table, $join, $column, $where) . ' LIMIT 1'); + + if ($query) + { + $data = $query->fetchAll(PDO::FETCH_ASSOC); + + if (isset($data[ 0 ])) + { + $column = $where == null ? $join : $column; + + if (is_string($column) && $column != '*') + { + return $data[ 0 ][ $column ]; + } + + return $data[ 0 ]; + } + else + { + return false; + } + } + else + { + return false; + } + } + + public function has($table, $join, $where = null) + { + $column = null; + + $query = $this->query('SELECT EXISTS(' . $this->select_context($table, $join, $column, $where, 1) . ')'); + + if ($query) + { + return $query->fetchColumn() === '1'; + } + else + { + return false; + } + } + + public function count($table, $join = null, $column = null, $where = null) + { + $query = $this->query($this->select_context($table, $join, $column, $where, 'COUNT')); + + return $query ? 0 + $query->fetchColumn() : false; + } + + public function max($table, $join, $column = null, $where = null) + { + $query = $this->query($this->select_context($table, $join, $column, $where, 'MAX')); + + if ($query) + { + $max = $query->fetchColumn(); + + return is_numeric($max) ? $max + 0 : $max; + } + else + { + return false; + } + } + + public function min($table, $join, $column = null, $where = null) + { + $query = $this->query($this->select_context($table, $join, $column, $where, 'MIN')); + + if ($query) + { + $min = $query->fetchColumn(); + + return is_numeric($min) ? $min + 0 : $min; + } + else + { + return false; + } + } + + public function avg($table, $join, $column = null, $where = null) + { + $query = $this->query($this->select_context($table, $join, $column, $where, 'AVG')); + + return $query ? 0 + $query->fetchColumn() : false; + } + + public function sum($table, $join, $column = null, $where = null) + { + $query = $this->query($this->select_context($table, $join, $column, $where, 'SUM')); + + return $query ? 0 + $query->fetchColumn() : false; + } + + public function action($actions) + { + if (is_callable($actions)) + { + $this->pdo->beginTransaction(); + + $result = $actions($this); + + if ($result === false) + { + $this->pdo->rollBack(); + } + else + { + $this->pdo->commit(); + } + } + else + { + return false; + } + } + + public function debug() + { + $this->debug_mode = true; + + return $this; + } + + public function error() + { + return $this->pdo->errorInfo(); + } + + public function last_query() + { + return end($this->logs); + } + + public function log() + { + return $this->logs; + } + + public function info() + { + $output = array( + 'server' => 'SERVER_INFO', + 'driver' => 'DRIVER_NAME', + 'client' => 'CLIENT_VERSION', + 'version' => 'SERVER_VERSION', + 'connection' => 'CONNECTION_STATUS' + ); + + foreach ($output as $key => $value) + { + $output[ $key ] = $this->pdo->getAttribute(constant('PDO::ATTR_' . $value)); + } + + return $output; + } +} +?> \ No newline at end of file diff --git a/vendor/catfan/medoo/src/medoo-logo.png b/vendor/catfan/medoo/src/medoo-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..914885487fca03651e9cfa9e8d0b06761cc27212 GIT binary patch literal 37776 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 + * Jordi Boggiano + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Composer\Autoload; + +/** + * ClassLoader implements a PSR-0, PSR-4 and classmap class loader. + * + * $loader = new \Composer\Autoload\ClassLoader(); + * + * // register classes with namespaces + * $loader->add('Symfony\Component', __DIR__.'/component'); + * $loader->add('Symfony', __DIR__.'/framework'); + * + * // activate the autoloader + * $loader->register(); + * + * // to enable searching the include path (eg. for PEAR packages) + * $loader->setUseIncludePath(true); + * + * In this example, if you try to use a class in the Symfony\Component + * namespace or one of its children (Symfony\Component\Console for instance), + * the autoloader will first look for the class under the component/ + * directory, and it will then fallback to the framework/ directory if not + * found before giving up. + * + * This class is loosely based on the Symfony UniversalClassLoader. + * + * @author Fabien Potencier + * @author Jordi Boggiano + * @see http://www.php-fig.org/psr/psr-0/ + * @see http://www.php-fig.org/psr/psr-4/ + */ +class ClassLoader +{ + // PSR-4 + private $prefixLengthsPsr4 = array(); + private $prefixDirsPsr4 = array(); + private $fallbackDirsPsr4 = array(); + + // PSR-0 + private $prefixesPsr0 = array(); + private $fallbackDirsPsr0 = array(); + + private $useIncludePath = false; + private $classMap = array(); + + private $classMapAuthoritative = false; + + public function getPrefixes() + { + if (!empty($this->prefixesPsr0)) { + return call_user_func_array('array_merge', $this->prefixesPsr0); + } + + return array(); + } + + public function getPrefixesPsr4() + { + return $this->prefixDirsPsr4; + } + + public function getFallbackDirs() + { + return $this->fallbackDirsPsr0; + } + + public function getFallbackDirsPsr4() + { + return $this->fallbackDirsPsr4; + } + + public function getClassMap() + { + return $this->classMap; + } + + /** + * @param array $classMap Class to filename map + */ + public function addClassMap(array $classMap) + { + if ($this->classMap) { + $this->classMap = array_merge($this->classMap, $classMap); + } else { + $this->classMap = $classMap; + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, either + * appending or prepending to the ones previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories + */ + public function add($prefix, $paths, $prepend = false) + { + if (!$prefix) { + if ($prepend) { + $this->fallbackDirsPsr0 = array_merge( + (array) $paths, + $this->fallbackDirsPsr0 + ); + } else { + $this->fallbackDirsPsr0 = array_merge( + $this->fallbackDirsPsr0, + (array) $paths + ); + } + + return; + } + + $first = $prefix[0]; + if (!isset($this->prefixesPsr0[$first][$prefix])) { + $this->prefixesPsr0[$first][$prefix] = (array) $paths; + + return; + } + if ($prepend) { + $this->prefixesPsr0[$first][$prefix] = array_merge( + (array) $paths, + $this->prefixesPsr0[$first][$prefix] + ); + } else { + $this->prefixesPsr0[$first][$prefix] = array_merge( + $this->prefixesPsr0[$first][$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, either + * appending or prepending to the ones previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories + * + * @throws \InvalidArgumentException + */ + public function addPsr4($prefix, $paths, $prepend = false) + { + if (!$prefix) { + // Register directories for the root namespace. + if ($prepend) { + $this->fallbackDirsPsr4 = array_merge( + (array) $paths, + $this->fallbackDirsPsr4 + ); + } else { + $this->fallbackDirsPsr4 = array_merge( + $this->fallbackDirsPsr4, + (array) $paths + ); + } + } elseif (!isset($this->prefixDirsPsr4[$prefix])) { + // Register directories for a new namespace. + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } elseif ($prepend) { + // Prepend directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + (array) $paths, + $this->prefixDirsPsr4[$prefix] + ); + } else { + // Append directories for an already registered namespace. + $this->prefixDirsPsr4[$prefix] = array_merge( + $this->prefixDirsPsr4[$prefix], + (array) $paths + ); + } + } + + /** + * Registers a set of PSR-0 directories for a given prefix, + * replacing any others previously set for this prefix. + * + * @param string $prefix The prefix + * @param array|string $paths The PSR-0 base directories + */ + public function set($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr0 = (array) $paths; + } else { + $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths; + } + } + + /** + * Registers a set of PSR-4 directories for a given namespace, + * replacing any others previously set for this namespace. + * + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param array|string $paths The PSR-4 base directories + * + * @throws \InvalidArgumentException + */ + public function setPsr4($prefix, $paths) + { + if (!$prefix) { + $this->fallbackDirsPsr4 = (array) $paths; + } else { + $length = strlen($prefix); + if ('\\' !== $prefix[$length - 1]) { + throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); + } + $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; + $this->prefixDirsPsr4[$prefix] = (array) $paths; + } + } + + /** + * Turns on searching the include path for class files. + * + * @param bool $useIncludePath + */ + public function setUseIncludePath($useIncludePath) + { + $this->useIncludePath = $useIncludePath; + } + + /** + * Can be used to check if the autoloader uses the include path to check + * for classes. + * + * @return bool + */ + public function getUseIncludePath() + { + return $this->useIncludePath; + } + + /** + * Turns off searching the prefix and fallback directories for classes + * that have not been registered with the class map. + * + * @param bool $classMapAuthoritative + */ + public function setClassMapAuthoritative($classMapAuthoritative) + { + $this->classMapAuthoritative = $classMapAuthoritative; + } + + /** + * Should class lookup fail if not found in the current class map? + * + * @return bool + */ + public function isClassMapAuthoritative() + { + return $this->classMapAuthoritative; + } + + /** + * Registers this instance as an autoloader. + * + * @param bool $prepend Whether to prepend the autoloader or not + */ + public function register($prepend = false) + { + spl_autoload_register(array($this, 'loadClass'), true, $prepend); + } + + /** + * Unregisters this instance as an autoloader. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'loadClass')); + } + + /** + * Loads the given class or interface. + * + * @param string $class The name of the class + * @return bool|null True if loaded, null otherwise + */ + public function loadClass($class) + { + if ($file = $this->findFile($class)) { + includeFile($file); + + return true; + } + } + + /** + * Finds the path to the file where the class is defined. + * + * @param string $class The name of the class + * + * @return string|false The path if found, false otherwise + */ + public function findFile($class) + { + // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 + if ('\\' == $class[0]) { + $class = substr($class, 1); + } + + // class map lookup + if (isset($this->classMap[$class])) { + return $this->classMap[$class]; + } + if ($this->classMapAuthoritative) { + return false; + } + + $file = $this->findFileWithExtension($class, '.php'); + + // Search for Hack files if we are running on HHVM + if ($file === null && defined('HHVM_VERSION')) { + $file = $this->findFileWithExtension($class, '.hh'); + } + + if ($file === null) { + // Remember that this class does not exist. + return $this->classMap[$class] = false; + } + + return $file; + } + + private function findFileWithExtension($class, $ext) + { + // PSR-4 lookup + $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext; + + $first = $class[0]; + if (isset($this->prefixLengthsPsr4[$first])) { + foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { + if (0 === strpos($class, $prefix)) { + foreach ($this->prefixDirsPsr4[$prefix] as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + return $file; + } + } + } + } + } + + // PSR-4 fallback dirs + foreach ($this->fallbackDirsPsr4 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) { + return $file; + } + } + + // PSR-0 lookup + if (false !== $pos = strrpos($class, '\\')) { + // namespaced class name + $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1) + . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR); + } else { + // PEAR-like class name + $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext; + } + + if (isset($this->prefixesPsr0[$first])) { + foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) { + if (0 === strpos($class, $prefix)) { + foreach ($dirs as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + } + } + } + + // PSR-0 fallback dirs + foreach ($this->fallbackDirsPsr0 as $dir) { + if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) { + return $file; + } + } + + // PSR-0 include paths. + if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) { + return $file; + } + } +} + +/** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ +function includeFile($file) +{ + include $file; +} diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE new file mode 100644 index 0000000..1a28124 --- /dev/null +++ b/vendor/composer/LICENSE @@ -0,0 +1,21 @@ + +Copyright (c) 2016 Nils Adermann, Jordi Boggiano + +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/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php new file mode 100644 index 0000000..7a91153 --- /dev/null +++ b/vendor/composer/autoload_classmap.php @@ -0,0 +1,9 @@ + $vendorDir . '/catfan/medoo/medoo.php', +); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php new file mode 100644 index 0000000..b7fc012 --- /dev/null +++ b/vendor/composer/autoload_namespaces.php @@ -0,0 +1,9 @@ += 50600 && !defined('HHVM_VERSION'); + if ($useStaticLoader) { + require_once __DIR__ . '/autoload_static.php'; + + call_user_func(\Composer\Autoload\ComposerStaticInit0265aadecade0cc9d40a1209ba2a0dca::getInitializer($loader)); + } else { + $map = require __DIR__ . '/autoload_namespaces.php'; + foreach ($map as $namespace => $path) { + $loader->set($namespace, $path); + } + + $map = require __DIR__ . '/autoload_psr4.php'; + foreach ($map as $namespace => $path) { + $loader->setPsr4($namespace, $path); + } + + $classMap = require __DIR__ . '/autoload_classmap.php'; + if ($classMap) { + $loader->addClassMap($classMap); + } + } + + $loader->register(true); + + if ($useStaticLoader) { + $includeFiles = Composer\Autoload\ComposerStaticInit0265aadecade0cc9d40a1209ba2a0dca::$files; + } else { + $includeFiles = require __DIR__ . '/autoload_files.php'; + } + foreach ($includeFiles as $fileIdentifier => $file) { + composerRequire0265aadecade0cc9d40a1209ba2a0dca($fileIdentifier, $file); + } + + return $loader; + } +} + +function composerRequire0265aadecade0cc9d40a1209ba2a0dca($fileIdentifier, $file) +{ + if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { + require $file; + + $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true; + } +} diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php new file mode 100644 index 0000000..5bab733 --- /dev/null +++ b/vendor/composer/autoload_static.php @@ -0,0 +1,19 @@ + __DIR__ . '/..' . '/catfan/medoo/medoo.php', + ); + + public static function getInitializer(ClassLoader $loader) + { + return \Closure::bind(function () use ($loader) { + + }, null, ClassLoader::class); + } +} diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json new file mode 100644 index 0000000..a310cf6 --- /dev/null +++ b/vendor/composer/installed.json @@ -0,0 +1,59 @@ +[ + { + "name": "catfan/medoo", + "version": "v1.0.2", + "version_normalized": "1.0.2.0", + "source": { + "type": "git", + "url": "https://github.com/catfan/Medoo.git", + "reference": "342e2d6a3bcf4adcac58e67593d63547139ab1ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/catfan/Medoo/zipball/342e2d6a3bcf4adcac58e67593d63547139ab1ac", + "reference": "342e2d6a3bcf4adcac58e67593d63547139ab1ac", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "php": ">=5.1" + }, + "suggest": { + "ext-pdo_dblib": "For MSSQL or Sybase databases on Linux/UNIX platform", + "ext-pdo_mysql": "For MySQL or MariaDB databases", + "ext-pdo_oci": "For Oracle databases", + "ext-pdo_pqsql": "For PostgreSQL databases", + "ext-pdo_sqlite": "For SQLite databases", + "ext-pdo_sqlsrv": "For MSSQL databases on Windows platform" + }, + "time": "2016-02-14 16:03:42", + "type": "framework", + "installation-source": "dist", + "autoload": { + "files": [ + "medoo.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Angel Lai", + "email": "angel@catfan.me" + } + ], + "description": "The Lightest PHP database framework to accelerate development", + "homepage": "http://medoo.in", + "keywords": [ + "database", + "lightweight", + "mssql", + "mysql", + "php framework", + "sql", + "sqlite" + ] + } +]