Last active
January 2, 2016 02:59
-
-
Save aweiand/8241243 to your computer and use it in GitHub Desktop.
Arquivo alterado sobre a RESTFull API para correção de problemas com o prostgresql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Alterações para aperfeiçoamento do postgre: (02/01/2014) | |
* - Adicionado teste de "is_numeric($data)" na linha 72 para poder trabalhar melhor com colunas que sejam inteiras e não utilizar "LIKE" no "WHERE" | |
* - Removidas as aspas "´" e "`" para funcionamento correto | |
* - Suprimida a opção "PDO::ATTR_AUTOCOMMIT => true" na linha 573 para correção de bug na conexão do PDO | |
*/ | |
$dsn = ''; | |
$clients = array | |
( | |
); | |
if (strcmp('cli', PHP_SAPI) === 0) { | |
exit('Arrest-DB should not be run from CLI.'); | |
} | |
if ((empty($clients) !== true) && (in_array($_SERVER['REMOTE_ADDR'], (array) $clients) !== true)) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 403, | |
'status' => 'Forbidden', | |
), | |
); | |
exit(ArrestDB::Reply($result)); | |
} else if (ArrestDB::Query($dsn) === false) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 503, | |
'status' => 'Service Unavailable', | |
), | |
); | |
exit(ArrestDB::Reply($result)); | |
} | |
if (array_key_exists('_method', $_GET) === true) { | |
$_SERVER['REQUEST_METHOD'] = strtoupper(trim($_GET['_method'])); | |
} else if (array_key_exists('HTTP_X_HTTP_METHOD_OVERRIDE', $_SERVER) === true) { | |
$_SERVER['REQUEST_METHOD'] = strtoupper(trim($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])); | |
} | |
ArrestDB::Serve('GET', '/(#any)/(#any)/(#any)', function ($table, $id, $data) { | |
$query = array | |
( | |
sprintf('SELECT * FROM %s', $table) | |
); | |
/* | |
* Adicionado teste de tipo para verificar se for inteiro e poder utilizar campos com nomes diferentes de id | |
* no get, sem prejuízos a consulta no postgresql | |
*/ | |
if (is_numeric($data)) | |
$query[] = sprintf('WHERE %s = ?', $id); | |
else | |
$query[] = sprintf('WHERE %s LIKE ?', $id); | |
if (isset($_GET['by']) === true) { | |
if (isset($_GET['order']) !== true) { | |
$_GET['order'] = 'ASC'; | |
} | |
$query[] = sprintf('ORDER BY %s %s', $_GET['by'], $_GET['order']); | |
} | |
if (isset($_GET['limit']) === true) { | |
$query[] = sprintf('LIMIT %u', $_GET['limit']); | |
if (isset($_GET['offset']) === true) { | |
$query[] = sprintf('OFFSET %u', $_GET['offset']); | |
} | |
} | |
$query = sprintf('%s;', implode(' ', $query)); | |
$result = ArrestDB::Query($query, $data); | |
if ($result === false) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 404, | |
'status' => 'Not Found', | |
), | |
); | |
} else if (empty($result) === true) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 204, | |
'status' => 'No Content', | |
), | |
); | |
} | |
return ArrestDB::Reply($result); | |
}); | |
ArrestDB::Serve('GET', '/(#any)/(#num)?', function ($table, $id = null) { | |
$query = array | |
( | |
sprintf('SELECT * FROM %s', $table), | |
); | |
if (isset($id) === true) { | |
$query[] = sprintf('WHERE %s = ? LIMIT 1', 'id'); | |
} else { | |
if (isset($_GET['by']) === true) { | |
if (isset($_GET['order']) !== true) { | |
$_GET['order'] = 'ASC'; | |
} | |
$query[] = sprintf('ORDER BY %s %s', $_GET['by'], $_GET['order']); | |
} | |
if (isset($_GET['limit']) === true) { | |
$query[] = sprintf('LIMIT %u', $_GET['limit']); | |
if (isset($_GET['offset']) === true) { | |
$query[] = sprintf('OFFSET %u', $_GET['offset']); | |
} | |
} | |
} | |
$query = sprintf('%s;', implode(' ', $query)); | |
$result = (isset($id) === true) ? ArrestDB::Query($query, $id) : ArrestDB::Query($query); | |
if ($result === false) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 404, | |
'status' => 'Not Found', | |
), | |
); | |
} else if (empty($result) === true) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 204, | |
'status' => 'No Content', | |
), | |
); | |
} else if (isset($id) === true) { | |
$result = array_shift($result); | |
} | |
return ArrestDB::Reply($result); | |
}); | |
ArrestDB::Serve('DELETE', '/(#any)/(#num)', function ($table, $id) { | |
$query = array | |
( | |
sprintf('DELETE FROM %s WHERE %s = ?', $table, 'id'), | |
); | |
$query = sprintf('%s;', implode(' ', $query)); | |
$result = ArrestDB::Query($query, $id); | |
if ($result === false) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 404, | |
'status' => 'Not Found', | |
), | |
); | |
} else if (empty($result) === true) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 204, | |
'status' => 'No Content', | |
), | |
); | |
} else { | |
$result = array | |
( | |
'success' => array | |
( | |
'code' => 200, | |
'status' => 'OK', | |
), | |
); | |
} | |
return ArrestDB::Reply($result); | |
}); | |
if (in_array($http = strtoupper($_SERVER['REQUEST_METHOD']), array('POST', 'PUT')) === true) { | |
if (preg_match('~^\x78[\x01\x5E\x9C\xDA]~', $data = file_get_contents('php://input')) > 0) { | |
$data = gzuncompress($data); | |
} | |
if ((array_key_exists('CONTENT_TYPE', $_SERVER) === true) && (empty($data) !== true)) { | |
if (strcasecmp($_SERVER['CONTENT_TYPE'], 'application/json') === 0) { | |
$GLOBALS['_' . $http] = json_decode($data, true); | |
} else if ((strcasecmp($_SERVER['CONTENT_TYPE'], 'application/x-www-form-urlencoded') === 0) && (strcasecmp($_SERVER['REQUEST_METHOD'], 'PUT') === 0)) { | |
parse_str($data, $GLOBALS['_' . $http]); | |
} | |
} | |
if ((isset($GLOBALS['_' . $http]) !== true) || (is_array($GLOBALS['_' . $http]) !== true)) { | |
$GLOBALS['_' . $http] = array(); | |
} | |
unset($data); | |
} | |
ArrestDB::Serve('POST', '/(#any)', function ($table) { | |
if (empty($_POST) === true) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 204, | |
'status' => 'No Content', | |
), | |
); | |
} else if (is_array($_POST) === true) { | |
$queries = array(); | |
if (count($_POST) == count($_POST, COUNT_RECURSIVE)) { | |
$_POST = array($_POST); | |
} | |
foreach ($_POST as $row) { | |
$data = array(); | |
foreach ($row as $key => $value) { | |
$data[sprintf('%s', $key)] = '?'; | |
} | |
$query = array | |
( | |
sprintf('INSERT INTO %s (%s) VALUES (%s)', $table, implode(', ', array_keys($data)), implode(', ', $data)), | |
); | |
$queries[] = array | |
( | |
sprintf('%s;', implode(' ', $query)), | |
$data, | |
); | |
} | |
if (count($queries) > 1) { | |
ArrestDB::Query()->beginTransaction(); | |
while (is_null($query = array_shift($queries)) !== true) { | |
if (($result = ArrestDB::Query($query[0], $query[1])) === false) { | |
ArrestDB::Query()->rollBack(); | |
break; | |
} | |
} | |
if (($result !== false) && (ArrestDB::Query()->inTransaction() === true)) { | |
$result = ArrestDB::Query()->commit(); | |
} | |
} else if (is_null($query = array_shift($queries)) !== true) { | |
$result = ArrestDB::Query($query[0], $query[1]); | |
} | |
if ($result === false) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 409, | |
'status' => 'Conflict', | |
), | |
); | |
} else { | |
$result = array | |
( | |
'success' => array | |
( | |
'code' => 201, | |
'status' => 'Created', | |
), | |
); | |
} | |
} | |
return ArrestDB::Reply($result); | |
}); | |
ArrestDB::Serve('PUT', '/(#any)/(#num)', function ($table, $id) { | |
if (empty($GLOBALS['_PUT']) === true) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 204, | |
'status' => 'No Content', | |
), | |
); | |
} else if (is_array($GLOBALS['_PUT']) === true) { | |
$data = array(); | |
foreach ($GLOBALS['_PUT'] as $key => $value) { | |
$data[$key] = sprintf('%s = ?', $key); | |
} | |
$query = array | |
( | |
sprintf('UPDATE %s SET %s WHERE %s = ?', $table, implode(', ', $data), 'id'), | |
); | |
$query = sprintf('%s;', implode(' ', $query)); | |
$result = ArrestDB::Query($query, $GLOBALS['_PUT']); | |
if ($result === false) { | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 409, | |
'status' => 'Conflict', | |
), | |
); | |
} else { | |
$result = array | |
( | |
'success' => array | |
( | |
'code' => 200, | |
'status' => 'OK', | |
), | |
); | |
} | |
} | |
return ArrestDB::Reply($result); | |
}); | |
$result = array | |
( | |
'error' => array | |
( | |
'code' => 400, | |
'status' => 'Bad Request', | |
), | |
); | |
exit(ArrestDB::Reply($result)); | |
class ArrestDB { | |
public static function Query($query = null) { | |
static $db = null; | |
static $result = array(); | |
try { | |
if (isset($db, $query) === true) { | |
if (empty($result[$hash = crc32($query)]) === true) { | |
$result[$hash] = $db->prepare($query); | |
} | |
$data = array_slice(func_get_args(), 1); | |
if (count($data, COUNT_RECURSIVE) > count($data)) { | |
$data = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveArrayIterator($data)), false); | |
} | |
if ($result[$hash]->execute($data) === true) { | |
$sequence = null; | |
if ((strncmp('pgsql', $db->getAttribute(\PDO::ATTR_DRIVER_NAME), 5) === 0) && (sscanf($query, 'INSERT INTO %s', $sequence) > 0)) { | |
$sequence = sprintf('%s_id_seq', trim($sequence, '')); | |
} | |
switch (strstr($query, ' ', true)) { | |
case 'INSERT': | |
case 'REPLACE': | |
return $db->lastInsertId($sequence); | |
case 'UPDATE': | |
case 'DELETE': | |
return $result[$hash]->rowCount(); | |
case 'SELECT': | |
case 'EXPLAIN': | |
case 'PRAGMA': | |
case 'SHOW': | |
return $result[$hash]->fetchAll(); | |
} | |
return true; | |
} | |
return false; | |
} else if (isset($query) === true) { | |
$options = array | |
( | |
\PDO::ATTR_CASE => \PDO::CASE_NATURAL, | |
\PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, | |
\PDO::ATTR_EMULATE_PREPARES => false, | |
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, | |
\PDO::ATTR_ORACLE_NULLS => \PDO::NULL_NATURAL, | |
\PDO::ATTR_STRINGIFY_FETCHES => false, | |
); | |
if (preg_match('~^sqlite://([[:print:]]++)$~i', $query, $dsn) > 0) { | |
$options += array | |
( | |
\PDO::ATTR_TIMEOUT => 3, | |
); | |
$db = new \PDO(sprintf('sqlite:%s', $dsn[1]), null, null, $options); | |
$pragmas = array | |
( | |
'automatic_index' => 'ON', | |
'cache_size' => '8192', | |
'foreign_keys' => 'ON', | |
'journal_size_limit' => '67110000', | |
'locking_mode' => 'NORMAL', | |
'page_size' => '4096', | |
'recursive_triggers' => 'ON', | |
'secure_delete' => 'ON', | |
'synchronous' => 'NORMAL', | |
'temp_store' => 'MEMORY', | |
'journal_mode' => 'WAL', | |
'wal_autocheckpoint' => '4096', | |
); | |
if (strncasecmp('WIN', PHP_OS, 3) !== 0) { | |
$memory = 131072; | |
if (($page = intval(shell_exec('getconf PAGESIZE'))) > 0) { | |
$pragmas['page_size'] = $page; | |
} | |
if (is_readable('/proc/meminfo') === true) { | |
if (is_resource($handle = fopen('/proc/meminfo', 'rb')) === true) { | |
while (($line = fgets($handle, 1024)) !== false) { | |
if (sscanf($line, 'MemTotal: %d kB', $memory) == 1) { | |
$memory = round($memory / 131072) * 131072; | |
break; | |
} | |
} | |
fclose($handle); | |
} | |
} | |
$pragmas['cache_size'] = intval($memory * 0.25 / ($pragmas['page_size'] / 1024)); | |
$pragmas['wal_autocheckpoint'] = $pragmas['cache_size'] / 2; | |
} | |
foreach ($pragmas as $key => $value) { | |
$db->exec(sprintf('PRAGMA %s=%s;', $key, $value)); | |
} | |
} else if (preg_match('~^(mysql|pgsql)://(?:(.+?)(?::(.+?))?@)?([^/:@]++)(?::(\d++))?/(\w++)/?$~i', $query, $dsn) > 0) { | |
/* | |
* Bug na Classe/Driver que não permite trocar o tipo de autocommit | |
* $options += array | |
* ( | |
* \PDO::ATTR_AUTOCOMMIT => true, | |
* ); | |
*/ | |
if (strncasecmp('mysql', $query, 5) === 0) { | |
$options += array | |
( | |
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES "utf8" COLLATE "utf8_general_ci", time_zone = "+00:00";', | |
\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, | |
); | |
} | |
$db = new \PDO(sprintf('%s:host=%s;port=%s;dbname=%s', $dsn[1], $dsn[4], $dsn[5], $dsn[6]), $dsn[2], $dsn[3], $options); | |
} | |
} | |
} catch (\Exception $e) { | |
return false; | |
} | |
return (isset($db) === true) ? $db : false; | |
} | |
public static function Reply($data) { | |
$bitmask = 0; | |
$options = array('UNESCAPED_SLASHES', 'UNESCAPED_UNICODE'); | |
if (empty($_SERVER['HTTP_X_REQUESTED_WITH']) === true) { | |
$options[] = 'PRETTY_PRINT'; | |
} | |
foreach ($options as $option) { | |
$bitmask |= (defined('JSON_' . $option) === true) ? constant('JSON_' . $option) : 0; | |
} | |
if (($result = json_encode($data, $bitmask)) !== false) { | |
$callback = null; | |
if (array_key_exists('callback', $_GET) === true) { | |
$callback = trim(preg_replace('~[^[:alnum:]\[\]_.]~', '', $_GET['callback'])); | |
if (empty($callback) !== true) { | |
$result = sprintf('%s(%s);', $callback, $result); | |
} | |
} | |
if (headers_sent() !== true) { | |
header(sprintf('Content-Type: application/%s; charset=utf-8', (empty($callback) === true) ? 'json' : 'javascript')); | |
} | |
} | |
return $result; | |
} | |
public static function Serve($on = null, $route = null, $callback = null) { | |
static $root = null; | |
if (isset($_SERVER['REQUEST_METHOD']) !== true) { | |
$_SERVER['REQUEST_METHOD'] = 'CLI'; | |
} | |
if ((empty($on) === true) || (strcasecmp($on, $_SERVER['REQUEST_METHOD']) === 0)) { | |
if (is_null($root) === true) { | |
$root = preg_replace('~/++~', '/', substr($_SERVER['PHP_SELF'], strlen($_SERVER['SCRIPT_NAME'])) . '/'); | |
} | |
if (preg_match('~^' . str_replace(array('#any', '#num'), array('[^/]++', '[0-9]++'), $route) . '~i', $root, $parts) > 0) { | |
return (empty($callback) === true) ? true : exit(call_user_func_array($callback, array_slice($parts, 1))); | |
} | |
} | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment