/** * Prepare a phramework instance * @uses Bootstrap::getSettings() to fetch the settings * @return Phramework */ public static function prepare() { $settings = self::getSettings(); $phramework = new Phramework($settings, new \Phramework\URIStrategy\URITemplate([['/', '\\Phramework\\SystemLog\\APP\\Controllers\\DummyController', 'GET', Phramework::METHOD_ANY], ['/dummy/', '\\Phramework\\SystemLog\\APP\\Controllers\\DummyController', 'GET', Phramework::METHOD_ANY], ['/dummy/{id}', '\\Phramework\\SystemLog\\APP\\Controllers\\DummyController', 'GETById', Phramework::METHOD_ANY]])); \Phramework\Database\Database::setAdapter(new \Phramework\Database\MySQL($settings['database'])); return $phramework; }
/** * Update database records * @param string|integer $id * @param array|object $keysValues * @param string|array $table Table's name * @param string $idAttribute **[Optional]** Id attribute * @return integer Return number of affected records * @param null|integer $limit **[Optional]** * Limit clause, when null there is not limit. * @todo Add $additionalAttributes */ public static function update($id, $keysValues, $table, $idAttribute = 'id', $limit = 1) { //Work with arrays if (is_object($keysValues)) { $keysValues = (array) $keysValues; } $queryKeys = implode('" = ?,"', array_keys($keysValues)); $queryValues = array_values($keysValues); //Push id to the end $queryValues[] = $id; $tableName = ''; //Work with array if (is_object($table)) { $table = (array) $table; } if (is_array($table) && isset($table['schema']) && isset($table['table'])) { $tableName = sprintf('"%s"."%s"', $table['schema'], $table['table']); } else { $tableName = sprintf('"%s"', $table); } $query = sprintf('UPDATE %s SET "%s" = ? WHERE "%s" = ? %s', $tableName, $queryKeys, $idAttribute, $limit === null ? '' : ''); //Return number of rows affected $result = Database::execute($query, $queryValues); return $result; }
/** * @covers Phramework\QueryLog\QueryLog::register */ public function testRegister2() { try { \Phramework\Database\Database::execute('SELECT * FROM "boomboom"'); } catch (\Exception $e) { } \Phramework\Database\Database::execute('SELECT * FROM user'); \Phramework\Database\Database::execute('SELECT * FROM user WHERE "user"."id" = ? LIMIT 1', [1]); }
/** * Delete database records * @param string|integer $id * Id value * @param array|object $additionalAttributes * Additional attributes to use in WHERE $idAttribute * @param string|array $table Table's name * @param string $idAttribute **[Optional]** * Id attribute * @param null|integer $limit **[Optional]** * Limit clause, when null there is not limit. * @return integer Return number of affected records */ public static function delete($id, $additionalAttributes, $table, $idAttribute = 'id', $limit = 1) { //force disable limit because they wont work with postgreqsql $limit = null; $queryValues = [$id]; $additional = []; foreach ($additionalAttributes as $key => $value) { //push to additional $additional[] = sprintf('AND "%s"."%s" = ?', $table, $key); $queryValues[] = $value; } $tableName = ''; if (is_array($table) && isset($table['schema']) && isset($table['table'])) { $tableName = '"' . $table['schema'] . '"' . '."' . $table['table'] . '"'; } else { $tableName = '"' . $table . '"'; } $query = sprintf('DELETE FROM %s WHERE "%s" = ? %s %s', $tableName, $idAttribute, implode("\n", $additional), $limit === null ? '' : 'LIMIT ' . $limit); return Database::execute($query, $queryValues); }
/** * Create a new record in database * @param array|object $attributes Key-value array or object with records's attributes * @param string $table Table's name * @param string|null $schema *[Optional]* Table's schema, default is null for no schema * @param integer $return Return method type * - if **`RETURN_ID`** will return the id of last inserted record * - if **`RETURN_RECORDS`** will return the inserted record * - if **`RETURN_NUMBER_OF_RECORDS`** will return the number of records affected * @return integer|array * @throws ServerException * @todo Check RETURNING id for another primary key attribute */ public static function create($attributes, $table, $schema = null, $return = self::RETURN_ID) { if (is_object($attributes)) { $attributes = (array) $attributes; } $driver = Database::getAdapterName(); //prepare query $query_keys = implode('" , "', array_keys($attributes)); $query_parameter_string = trim(str_repeat('?,', count($attributes)), ','); $query_values = array_values($attributes); if ($driver == 'postgresql') { //Make sure boolean are strings foreach ($query_values as &$queryValue) { if (is_bool($queryValue)) { $queryValue = $queryValue ? 'true' : 'false'; } } } $query = 'INSERT INTO '; if ($schema !== null) { $query .= sprintf('"%s"."%s"', $schema, $table); } else { $query .= sprintf('"%s"', $table); } $query .= sprintf(' ("%s") VALUES (%s)', $query_keys, $query_parameter_string); if ($return == self::RETURN_ID) { //Return inserted id if ($driver == 'postgresql') { $query .= ' RETURNING id'; $id = Database::executeAndFetch($query, $query_values); return $id['id']; } return Database::executeLastInsertId($query, $query_values); } elseif ($return == self::RETURN_RECORDS) { //Return records if ($driver != 'postgresql') { throw new ServerExcetion('RETURN_RECORDS works only with postgresql adapter'); } $query .= 'RETURNING *'; return Database::executeAndFetch($query, $query_values); } else { //Return number of records affected return Database::execute($query, $query_values); } }
/** * Activate query-log * @param null|object $additionalParameters * Additional parameters to be stored in query logs * @return boolean Returns false if query log is disabled * @throws \Exception * @uses Phramework\Database\Database */ public function register($additionalParameters = null) { if ($additionalParameters && !is_object($additionalParameters)) { throw new \Exception('additionalParameters must be an object'); } //Ignore registration if disabled setting is set to true if (isset($this->settings->disabled) && $this->settings->disabled) { return false; } //Get current global adapter $internalAdapter = \Phramework\Database\Database::getAdapter(); if (!$internalAdapter) { throw new \Exception('Global database adapter is not initialized'); } //Create new QueryLogAdapter instance, using current global adapter $queryLogAdapter = new QueryLogAdapter($this->settings, $internalAdapter, $additionalParameters); //Set newly created QueryLogAdapter instance as global adapter \Phramework\Database\Database::setAdapter($queryLogAdapter); return true; }
public static function post($username) { return Database::execute('INSERT INTO "user" ("username") VALUES (?)', [$username]); }
/** * Execute the API * @throws \Phramework\Exceptions\PermissionException * @throws \Phramework\Exceptions\NotFoundException * @throws \Phramework\Exceptions\IncorrectParametersException * @throws \Phramework\Exceptions\RequestException * @todo change default timezone * @todo change default language * @todo initialize database if set * @todo @security deny access to any else referals */ public function invoke() { $params = new \stdClass(); $method = self::METHOD_GET; $headers = []; try { date_default_timezone_set('Europe/Athens'); if (self::getSetting('debug')) { error_reporting(E_ALL); ini_set('display_errors', '1'); } if (self::getSetting('errorlog_path')) { ini_set('error_log', self::getSetting('errorlog_path')); } //Check if callback is set (JSONP) if (isset($_GET['callback'])) { if (!\Phramework\Validate\Validate::isValidJsonpCallback($_GET['callback'])) { throw new \Phramework\Exceptions\IncorrectParametersException(['callback']); } self::$callback = $_GET['callback']; unset($_GET['callback']); } /* //Initialize Database connection if required or db set if (self::getSetting('require_db') || self::getSetting('db')) { \Phramework\Models\Database::requireDatabase(self::getSetting('db')); } //Unset from memory Database connection information unset(self::$settings['db']); */ //Get method from the request (HTTP) method $method = self::$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : self::METHOD_GET; //Check if the requested HTTP method method is allowed // @todo check error code if (!in_array($method, self::$methodWhitelist)) { throw new \Phramework\Exceptions\RequestException('Method not allowed'); } //Default value of response's header origin $origin = '*'; //Get request headers $headers = Models\Request::headers(); //Check origin header if (isset($headers['Origin'])) { $originHost = parse_url($headers['Origin'], PHP_URL_HOST); //Check if origin host is allowed if ($originHost && self::getSetting('allowed_referer') && in_array($originHost, self::getSetting('allowed_referer'))) { $origin = $headers['Origin']; } //@TODO @security else deny access } elseif (isset($_SERVER['HTTP_HOST']) && isset($_SERVER['REQUEST_URI'])) { $origin = '*'; //TODO Exctract origin from request url } //Send access control headers if (!headers_sent()) { header('Access-Control-Allow-Credentials: true'); header('Access-Control-Allow-Origin: ' . $origin); header('Access-Control-Allow-Methods: GET, POST, PUT, PATCH, HEAD, DELETE, OPTIONS'); header('Access-Control-Allow-Headers: ' . 'Origin, X-Requested-With, Content-Type, Accept, Authorization, Content-Encoding'); } //Catch OPTIONS request and kill it if ($method == self::METHOD_OPTIONS) { header('HTTP/1.1 200 OK'); exit; } //Merge all REQUEST parameters into $params array $params = (object) array_merge($_GET, $_POST, $_FILES); //TODO $_FILES only if POST OR PUT //Parse request body //@Todo add allowed content-types if (in_array($method, [self::METHOD_POST, self::METHOD_PATCH, self::METHOD_PUT, self::METHOD_DELETE])) { $CONTENT_TYPE = null; if (isset($headers[Request::HEADER_CONTENT_TYPE])) { $CONTENT_TYPE = explode(';', $headers[Request::HEADER_CONTENT_TYPE]); $CONTENT_TYPE = $CONTENT_TYPE[0]; } if ($CONTENT_TYPE === 'application/x-www-form-urlencoded') { //Decode and merge params parse_str(file_get_contents('php://input'), $input); if ($input && !empty($input)) { $params = (object) array_merge((array) $params, (array) $input); } } elseif (in_array($CONTENT_TYPE, ['application/json', 'application/vnd.api+json'], true)) { $input = trim(file_get_contents('php://input')); if (!empty($input)) { //note if input length is >0 and decode returns null then its bad data //json_last_error() $inputObject = json_decode($input); if (json_last_error() !== JSON_ERROR_NONE) { throw new \Phramework\Exceptions\RequestException('JSON parse error: ' . json_last_error_msg()); } if ($inputObject && !empty($inputObject)) { $params = (object) array_merge((array) $params, (array) $inputObject); } } } } //STEP_AFTER_AUTHENTICATION_CHECK self::$stepCallback->call(StepCallback::STEP_BEFORE_AUTHENTICATION_CHECK, $params, $method, $headers); //Authenticate request (check authentication) self::$user = \Phramework\Authentication\Manager::check($params, $method, $headers); //In case of array returned force type to be object if (is_array(self::$user)) { self::$user = (object) self::$user; } //STEP_AFTER_AUTHENTICATION_CHECK self::$stepCallback->call(StepCallback::STEP_AFTER_AUTHENTICATION_CHECK, $params, $method, $headers, [self::$user]); //Default language value $language = self::getSetting('language'); //Select request's language if (isset($_GET['this_language']) && self::getSetting('languages') && in_array($_GET['this_language'], self::getSetting('languages'))) { //Force requested language if ($_GET['this_language'] != $language) { $language = $_GET['this_language']; } unset($_GET['this_language']); } elseif (self::$user && property_exists(self::$user, 'language_code')) { // Use user's langugae $language = self::$user->language_code; } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && self::getSetting('languages')) { // Use Accept languge if provided $a = $_SERVER['HTTP_ACCEPT_LANGUAGE']; if (in_array($a, self::getSetting('languages'))) { $language = $a; } } //Set language variable self::$language = $language; //self::$translation->setLanguageCode($language); //STEP_BEFORE_CALL_URISTRATEGY self::$stepCallback->call(StepCallback::STEP_BEFORE_CALL_URISTRATEGY, $params, $method, $headers); //Call controller's method list($invokedController, $invokedMethod) = self::$URIStrategy->invoke($params, $method, $headers, self::$user); self::$stepCallback->call(StepCallback::STEP_AFTER_CALL_URISTRATEGY, $params, $method, $headers, [$invokedController, $invokedMethod]); //STEP_BEFORE_CLOSE self::$stepCallback->call(StepCallback::STEP_BEFORE_CLOSE, $params, $method, $headers); } catch (\Phramework\Exceptions\NotFoundException $exception) { self::errorView([(object) ['status' => $exception->getCode(), 'detail' => $exception->getMessage(), 'title' => $exception->getMessage()]], $exception->getCode(), $params, $method, $headers, $exception); } catch (\Phramework\Exceptions\RequestException $exception) { self::errorView([(object) ['status' => $exception->getCode(), 'detail' => $exception->getMessage(), 'title' => $exception->getMessage()]], $exception->getCode(), $params, $method, $headers, $exception); } catch (\Phramework\Exceptions\PermissionException $exception) { self::errorView([(object) ['status' => $exception->getCode(), 'detail' => $exception->getMessage(), 'title' => $exception->getMessage()]], $exception->getCode(), $params, $method, $headers, $exception); } catch (\Phramework\Exceptions\UnauthorizedException $exception) { self::errorView([(object) ['status' => $exception->getCode(), 'detail' => $exception->getMessage(), 'title' => $exception->getMessage()]], $exception->getCode(), $params, $method, $headers, $exception); } catch (\Phramework\Exceptions\MissingParametersException $exception) { self::errorView([(object) ['status' => $exception->getCode(), 'detail' => $exception->getMessage(), 'meta' => ['missing' => $exception->getParameters()], 'title' => $exception->getMessage()]], $exception->getCode(), $params, $method, $headers, $exception); } catch (\Phramework\Exceptions\IncorrectParametersException $exception) { self::errorView([(object) ['status' => $exception->getCode(), 'detail' => $exception->getMessage(), 'meta' => ['incorrect' => $exception->getParameters()], 'title' => $exception->getMessage()]], $exception->getCode(), $params, $method, $headers, $exception); } catch (\Phramework\Exceptions\MethodNotAllowedException $exception) { //Write allow header if AllowedMethods is set if (!headers_sent() && $exception->getAllowedMethods()) { header('Allow: ' . implode(', ', $exception->getAllowedMethods())); } self::errorView([(object) ['status' => $exception->getCode(), 'detail' => $exception->getMessage(), 'meta' => ['allow' => $exception->getAllowedMethods()], 'title' => $exception->getMessage()]], $exception->getCode(), $params, $method, $headers, $exception); } catch (\Phramework\Exceptions\RequestException $exception) { self::errorView([(object) ['status' => $exception->getCode(), 'detail' => $exception->getMessage(), 'title' => 'Request Error']], $exception->getCode(), $params, $method, $headers, $exception); } catch (\Exception $exception) { self::errorView([(object) ['status' => 400, 'detail' => $exception->getMessage(), 'title' => 'Error']], 400, $params, $method, $headers, $exception); } finally { self::$stepCallback->call(StepCallback::STEP_FINALLY, $params, $method, $headers); //Unset all unset($params); //Try to close the databse \Phramework\Database\Database::close(); } }