diff options
| author | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
|---|---|---|
| committer | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
| commit | 4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch) | |
| tree | 5c07151ae61276d334e88f6309c30d439a85c12e /lib/classes/StudipPDO.class.php | |
| parent | da0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff) | |
| parent | 97a188592c679890a25c37ab78463add76a52ff7 (diff) | |
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/classes/StudipPDO.class.php')
| -rw-r--r-- | lib/classes/StudipPDO.class.php | 413 |
1 files changed, 0 insertions, 413 deletions
diff --git a/lib/classes/StudipPDO.class.php b/lib/classes/StudipPDO.class.php deleted file mode 100644 index e77a37f..0000000 --- a/lib/classes/StudipPDO.class.php +++ /dev/null @@ -1,413 +0,0 @@ -<?php -/** - * StudipPDO.class.php - Stud.IP PDO class - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * @author Elmar Ludwig - * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 - * @category Stud.IP - */ - -/** - * This is a special variant of the standard PDO class that does - * not allow multiple statement execution. - */ -class StudipPDO extends PDO -{ - const PARAM_ARRAY = 100; - const PARAM_COLUMN = 101; - - // Counter for the queries sent to the database - public $query_count = 0; - public $queries = []; - - /** - * Verifies that the given SQL query only contains a single statement. - * - * @param string SQL statement to check - * @throws PDOException when the query contains multiple statements - */ - protected function verify($statement) - { - if (mb_strpos($statement, ';') !== false) { - if (preg_match('/;\s*\S/', self::replaceStrings($statement))) { - throw new PDOException('multiple statement execution not allowed'); - } - } - - // Count executed queries (this is placed here since this is the only - // method that is executed on every call to the database) - $this->query_count += 1; - - if (!empty($GLOBALS['DEBUG_ALL_DB_QUERIES'])) { - $trace = debug_backtrace(); - - $classes = []; - if (isset($trace[2]['class']) && $trace[2]['class'] === 'SimpleORMap') { - $classes[] = 'sorm'; - } - if (isset($trace[1]) && $trace[1]['function'] === 'prepare') { - $classes[] = 'prepared'; - } - - $this->queries[] = [ - 'query' => implode("\n", array_filter(array_map('trim', explode("\n", $statement)))), - 'classes' => implode(' ', $classes), - 'trace' => $GLOBALS['DEBUG_ALL_DB_QUERIES_WITH_TRACE'] - ? array_slice($trace, 2) - : null, - ]; - } - } - - /** - * Replaces all string literals in the statement with placeholders. - * - * @param string SQL statement - * @return string modified SQL statement - */ - protected static function replaceStrings($statement) - { - $count = mb_substr_count($statement, '"') + mb_substr_count($statement, "'") + mb_substr_count($statement, '\\'); - - // use fast preg_replace() variant if possible - if ($count < 1000) { - $result = preg_replace('/"(""|\\\\.|[^\\\\"]+)*"|\'(\'\'|\\\\.|[^\\\\\']+)*\'/s', '?', $statement); - } - - if (!isset($result)) { - // split string into parts at quotes and backslash - $parts = preg_split('/([\\\\"\'])/', $statement, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); - $result = ''; - $quote_chr = null; - - for ($part = current($parts); $part !== false; $part = next($parts)) { - // inside quotes, "" is ", '' is ' and \x is x - if ($quote_chr !== NULL) { - if ($part === $quote_chr) { - $part = next($parts); - - if ($part !== $quote_chr) { - // backtrack and terminate string - prev($parts); - $result .= '?'; - $quote_chr = NULL; - } - } else if ($part === '\\') { - // skip next part - next($parts); - } - } else if ($part === "'" || $part === '"') { - $quote_chr = $part; - $saved_pos = key($parts); - } else { - $result .= $part; - } - } - - if ($quote_chr !== NULL) { - // unterminated quote: copy to end of string - $result .= implode(array_slice($parts, $saved_pos)); - } - } - - return $result; - } - - /** - * Quotes the given value in a form appropriate for the type. - * If no explicit type is given, the value's PHP type is used. - * - * @param mixed $value PHP value to quote - * @param ?int $type parameter type (e.g. PDO::PARAM_STR) - * @return string|false quoted SQL string - * - * @todo Add string|false return type when Stud.IP requires PHP8 minimal - */ - #[ReturnTypeWillChange] - public function quote($value, $type = null) - { - if (!isset($type)) { - if (is_null($value)) { - $type = PDO::PARAM_NULL; - } else if (is_bool($value)) { - $type = PDO::PARAM_BOOL; - } else if (is_int($value)) { - $type = PDO::PARAM_INT; - } else if (is_array($value)) { - $type = StudipPDO::PARAM_ARRAY; - } else { - $type = PDO::PARAM_STR; - } - } - - switch ($type) { - case PDO::PARAM_NULL: - return 'NULL'; - case PDO::PARAM_BOOL: - return $value ? '1' : '0'; - case PDO::PARAM_INT: - return (int) $value; - case StudipPDO::PARAM_ARRAY: - return is_array($value) && count($value) ? join(',', array_map([$this, 'quote'], $value)) : 'NULL'; - case StudipPDO::PARAM_COLUMN: - return preg_replace('/\\W/', '', $value); - default: - return parent::quote($value); - } - } - - /** - * Executes an SQL statement and returns the number of affected rows. - * - * @param string SQL statement - * @return int|false number of affected rows - * - * @todo Add mixed return type when Stud.IP requires PHP8 minimal - */ - #[ReturnTypeWillChange] - public function exec($statement) - { - $this->verify($statement); - return parent::exec($statement); - } - - /** - * Executes an SQL statement, returning a result set as a statement object. - * - * @param string $statement SQL statement - * @param int $fetch_mode fetch mode (optional) - * @param mixed ...$fetch_args fetch mode parameters (see PDOStatement::setFetchMode) - * @return object PDOStatement object - */ - #[ReturnTypeWillChange] - public function query($statement, $fetch_mode = NULL, ...$fetch_args) - { - $this->verify($statement); - - if (isset($fetch_mode)) { - $stmt = parent::query($statement, $fetch_mode, ...$fetch_args); - } else { - $stmt = parent::query($statement); - } - - $studip_stmt = new StudipPDOStatement($this, $statement, []); - $studip_stmt->setStatement($stmt); - return $studip_stmt; - } - - /** - * Prepares a statement for execution and returns a statement object. - * - * @param string $statement SQL statement - * @param array $driver_options - * - * @return StudipPDOStatement - */ - #[ReturnTypeWillChange] - public function prepare($statement, $driver_options = []) - { - $this->verify($statement); - return new StudipPDOStatement($this, $statement, $driver_options); - } - - /** - * This method is intended only for use by the StudipPDOStatement class. - * - * @param string SQL statement - * @return object PDOStatement object - */ - public function prepareStatement($statement, $driver_options = []) - { - return parent::prepare($statement, $driver_options); - } - - /** - * Executes sql statement with given parameters, - * returns number of affected rows, use only for INSERT,UPDATE etc - * - * @param string $statement SQL statement to execute - * @param array $input_parameters parameters for statement - * @return integer number of affected rows - */ - public function execute($statement, $input_parameters = null) - { - $st = $this->prepare($statement); - $ok = $st->execute($input_parameters); - if ($ok === true) { - return $st->rowCount(); - } - return 0; - } - - /** - * Executes sql statement with given parameters, and fetch results - * as sequential array, each row as associative array - * optionally apply given callable on each row, with current row and key as parameter - * - * @param string $statement SQL statement to execute - * @param array $input_parameters parameters for statement - * @param callable $callable callable to be applied to each of the rows - * @return array result set as array of assoc arrays - */ - public function fetchAll($statement, $input_parameters = null, $callable = null) - { - $st = $this->prepare($statement); - $st->execute($input_parameters); - if (is_callable($callable)) { - $data = []; - $st->setFetchMode(PDO::FETCH_ASSOC); - foreach ($st as $key => $row) { - $data[$key] = call_user_func($callable, $row, $key); - } - } else { - $data = $st->fetchAll(PDO::FETCH_ASSOC); - } - return $data; - } - - /** - * Executes sql statement with given parameters, and fetch only - * the values from first column as sequential array - * optionally apply given callable on each row, with current value and key as parameter - * - * @see StudipPDOStatement::fetchFirst() - * @param string $statement SQL statement to execute - * @param array $input_parameters parameters for statement - * @param callable $callable callable to be applied to each of the rows - * @return array result set - */ - public function fetchFirst($statement, $input_parameters = null, $callable = null) - { - $st = $this->prepare($statement); - $st->execute($input_parameters); - $data = $st->fetchFirst(); - if (is_callable($callable)) { - foreach ($data as $key => $row) { - $data[$key] = call_user_func($callable, $row, $key); - } - } - return $data; - } - - /** - * Executes sql statement with given parameters, and fetch results - * as associative array, first columns value is used as a key, the others are grouped - * optionally apply given callable on each grouped row, with current row and key as parameter - * if no callable is given, 'current' is used, to return the first entry of the grouped row - * - * @see StudipPDOStatement::fetchGrouped() - * @param string $statement SQL statement to execute - * @param array $input_parameters parameters for statement - * @param callable $callable callable to be applied to each of the rows - * @return array result set - */ - public function fetchGrouped($statement, $input_parameters = null, $callable = null) - { - $st = $this->prepare($statement); - $st->execute($input_parameters); - $data = $st->fetchGrouped(PDO::FETCH_ASSOC, is_null($callable) ? 'current' : null); - if (is_callable($callable)) { - foreach ($data as $key => $row) { - $data[$key] = call_user_func($callable, $row, $key); - } - } - return $data; - } - - /** - * Executes sql statement with given parameters, and fetch results - * as associative array, first columns value is used as a key, the other one is grouped - * use only when selecting 2 columns - * optionally apply given callable on each grouped row, with current row and key as parameter - * - * @see StudipPDOStatement::fetchGroupedPairs() - * @param string $statement SQL statement to execute - * @param array $input_parameters parameters for statement - * @param callable $callable callable to be applied to each of the rows - * @return array result set - */ - public function fetchGroupedPairs($statement, $input_parameters = null, $callable = null) - { - $st = $this->prepare($statement); - $st->execute($input_parameters); - $data = $st->fetchGroupedPairs(); - if (is_callable($callable)) { - foreach ($data as $key => $row) { - $data[$key] = call_user_func($callable, $row, $key); - } - } - return $data; - } - - /** - * Executes sql statement with given parameters, and fetch results - * as associative array, first columns value is used as a key, the other one as the value - * use only when selecting 2 columns - * optionally apply given callable on each grouped row, with current row and key as parameter - * - * @see StudipPDOStatement::fetchGroupedPairs() - * @param string $statement SQL statement to execute - * @param array $input_parameters parameters for statement - * @param callable $callable callable to be applied to each of the rows - * @return array result set - */ - public function fetchPairs($statement, $input_parameters = null, $callable = null) - { - $st = $this->prepare($statement); - $st->execute($input_parameters); - $data = $st->fetchPairs(); - if (is_callable($callable)) { - foreach ($data as $key => $row) { - $data[$key] = call_user_func($callable, $row, $key); - } - } - return $data; - } - - /** - * Executes sql statement with given parameters, and fetch only the first row - * as associative array - * - * @see StudipPDOStatement::fetchOne() - * @param string $statement SQL statement to execute - * @param array $input_parameters parameters for statement - * @return array first row of result set - */ - public function fetchOne($statement, $input_parameters = null) - { - $st = $this->prepare($statement); - $st->execute($input_parameters); - return $st->fetchOne(); - } - - /** - * Executes sql statement with given parameters, and fetch only the value of one column - * third param denotes the column, zero indexed - * - * @param string $statement SQL statement to execute - * @param array $input_parameters parameters for statement - * @param integer $column number of column to fetch - * @return string value of chosen column - */ - public function fetchColumn($statement, $input_parameters = null, $column = 0) - { - $st = $this->prepare($statement); - $st->execute($input_parameters); - return $st->fetchColumn($column); - } - - /** - * Determine if the connected database is a MariaDB database. - * - * @return bool - */ - public function isMariaDB(): bool - { - return stripos($this->getAttribute(\PDO::ATTR_SERVER_VERSION), 'MariaDB') !== false; - } -} |
