&–{@1†€p€`ÿJÈ—â@KðJ``’Iq€ÚRÀþJ@&–{@1†€à00ÿJ>ùÿ¼²Ð€fprintf°K`ÿJ KpN``’I‘÷J ­RúÀƒ&–{@1†þ0@K”ÅK¦ç€vfprintf±KpK`KP``’I1K Lr£ˆúÀƒ&–{@1†€€°K@˜â@pKàU``’I!K Lr£ˆå†@¥è‰O”†ˆ‡‰:†‰R¡‡"‰Ð€ÀKh˜â@ÀKðU``’IÑ K Lr£ˆå†@¥è‰O”†ˆ‡‰:†‰R¡‡"‰Ð€K˜â@K@]e`’I K Lr£ˆ˽{€þ†@…Ä… †B‰†Åû…°€`KÀ˜â@@Kà½``’IQ K Lr£ˆr*„P€Kø˜â@ Kð¾``’I K Lr£ˆr*„ò† Gp€`K0™â@ K€Ö``’I‘K Lr£ˆ#¡‡@熉p€P K`™â@ð KÖ``’I¡K Lr£ˆCË…@熉p€@ K˜™â@à KPÚ``’I±K Lr£ˆ¨Þ‡H†P€0 KÀ™â@° KÛ``’IáK Lr£ˆþ­ƒB‰P€ Kè™â@€ KÜ``’IK Lr£ˆ¨Þ‡Û†P€Ð Kšâ@PKPÝ``’IAK Lr£ˆ0€  K@šâ@KÞ``’I‘K Lr£ˆ@¦:‡@׆P€PKhšâ@ÐKÀÞ``’IÁK Lr£ˆD0€ K šâ@* @since 1.0 */ protected static $dbMinimum; /** * The depth of the current transaction. * * @var integer * @since 1.0 */ protected $transactionDepth = 0; /** * DatabaseFactory object * * @var DatabaseFactory * @since 2.0.0 */ protected $factory; /** * Query monitor object * * @var QueryMonitorInterface * @since 2.0.0 */ protected $monitor; /** * Get a list of available database connectors. * * The list will only be populated with connectors that the class exists for and the environment supports its use. * This gives us the ability to have a multitude of connector classes that are self-aware as to whether or not they * are able to be used on a given system. * * @return array An array of available database connectors. * * @since 1.0 */ public static function getConnectors() { if (empty(self::$connectors)) { // Get an iterator and loop trough the driver classes. $dir = __DIR__; $iterator = new \DirectoryIterator($dir); /** @var \DirectoryIterator $file */ foreach ($iterator as $file) { // Only load for php files. if (!$file->isDir()) { continue; } $baseName = $file->getBasename(); // Derive the class name from the type. /** @var DatabaseDriver $class */ $class = __NAMESPACE__ . '\\' . ucfirst(strtolower($baseName)) . '\\' . ucfirst(strtolower($baseName)) . 'Driver'; // If the class doesn't exist, or if it's not supported on this system, move on to the next type. if (!class_exists($class) || !$class::isSupported()) { continue; } // Everything looks good, add it to the list. self::$connectors[] = $baseName; } } return self::$connectors; } /** * Method to return a DatabaseDriver instance based on the given options. * * There are three global options and then the rest are specific to the database driver. * * - The 'driver' option defines which DatabaseDriver class is used for the connection -- the default is 'mysqli'. * - The 'database' option determines which database is to be used for the connection. * - The 'select' option determines whether the connector should automatically select the chosen database. * * Instances are unique to the given options and new objects are only created when a unique options array is * passed into the method. This ensures that we don't end up with unnecessary database connection resources. * * @param array $options Parameters to be passed to the database driver. * * @return DatabaseDriver * * @since 1.0 * @throws \RuntimeException * @deprecated 3.0 Use DatabaseFactory::getDriver() instead */ public static function getInstance(array $options = []) { trigger_deprecation( 'joomla/database', '2.0.0', '%s() is deprecated and will be removed in 3.0, use %s::getDriver() instead.', __METHOD__, DatabaseFactory::class ); // Sanitize the database connector options. $options['driver'] = isset($options['driver']) ? preg_replace('/[^A-Z0-9_\.-]/i', '', $options['driver']) : 'mysqli'; $options['database'] = $options['database'] ?? null; $options['select'] = $options['select'] ?? true; $options['factory'] = $options['factory'] ?? new DatabaseFactory(); $options['monitor'] = $options['monitor'] ?? null; // Get the options signature for the database connector. $signature = md5(serialize($options)); // If we already have a database connector instance for these options then just use that. if (empty(self::$instances[$signature])) { // Set the new connector to the global instances based on signature. self::$instances[$signature] = $options['factory']->getDriver($options['driver'], $options); } return self::$instances[$signature]; } /** * Splits a string of multiple queries into an array of individual queries. * * @param string $sql Input SQL string with which to split into individual queries. * * @return array * * @since 1.0 */ public static function splitSql($sql) { $start = 0; $open = false; $comment = false; $endString = ''; $end = \strlen($sql); $queries = []; $query = ''; for ($i = 0; $i < $end; $i++) { $current = substr($sql, $i, 1); $current2 = substr($sql, $i, 2); $current3 = substr($sql, $i, 3); $lenEndString = \strlen($endString); $testEnd = substr($sql, $i, $lenEndString); if ( $current === '"' || $current === "'" || $current2 === '--' || ($current2 === '/*' && $current3 !== '/*!' && $current3 !== '/*+') || ($current === '#' && $current3 !== '#__') || ($comment && $testEnd === $endString) ) { // Check if quoted with previous backslash $n = 2; while (substr($sql, $i - $n + 1, 1) === '\\' && $n < $i) { $n++; } // Not quoted if ($n % 2 === 0) { if ($open) { if ($testEnd === $endString) { if ($comment) { $comment = false; if ($lenEndString > 1) { $i += ($lenEndString - 1); $current = substr($sql, $i, 1); } $start = $i + 1; } $open = false; $endString = ''; } } else { $open = true; if ($current2 === '--') { $endString = "\n"; $comment = true; } elseif ($current2 === '/*') { $endString = '*/'; $comment = true; } elseif ($current === '#') { $endString = "\n"; $comment = true; } else { $endString = $current; } if ($comment && $start < $i) { $query .= substr($sql, $start, $i - $start); } } } } if ($comment) { $start = $i + 1; } if (($current === ';' && !$open) || $i === $end - 1) { if ($start <= $i) { $query .= substr($sql, $start, $i - $start + 1); } $query = trim($query); if ($query) { if (($i === $end - 1) && ($current !== ';')) { $query .= ';'; } $queries[] = $query; } $query = ''; $start = $i + 1; } $endComment = false; } return $queries; } /** * Magic method to access properties of the database driver. * * @param string $name The name of the property. * * @return mixed A value if the property name is valid, null otherwise. * * @since 1.4.0 * @deprecated 3.0 This is a B/C proxy since $this->name was previously public */ public function __get($name) { switch ($name) { case 'name': trigger_deprecation( 'joomla/database', '1.4.0', 'Accessing the name property of %s is deprecated, use the getName() method instead.', self::class ); return $this->getName(); default: $trace = debug_backtrace(); trigger_error( sprintf( 'Undefined property via __get(): %1$s in %2$s on line %3$s', $name, $trace[0]['file'], $trace[0]['line'] ), \E_USER_NOTICE ); } } /** * Constructor. * * @param array $options List of options used to configure the connection * * @since 1.0 */ public function __construct(array $options) { // Initialise object variables. $this->database = $options['database'] ?? ''; $this->tablePrefix = $options['prefix'] ?? ''; $this->count = 0; $this->errorNum = 0; // Set class options. $this->options = $options; // Register the DatabaseFactory $this->factory = $options['factory'] ?? new DatabaseFactory(); // Register the query monitor if available $this->monitor = $options['monitor'] ?? null; } /** * Destructor. * * @since 2.0.0 */ public function __destruct() { $this->disconnect(); } /** * Alter database's character set. * * @param string $dbName The database name that will be altered * * @return boolean|resource * * @since 2.0.0 * @throws \RuntimeException */ public function alterDbCharacterSet($dbName) { if ($dbName === null) { throw new \RuntimeException('Database name must not be null.'); } $this->setQuery($this->getAlterDbCharacterSet($dbName)); return $this->execute(); } /** * Create a new database using information from $options object. * * @param \stdClass $options Object used to pass user and database name to database driver. This object must have "db_name" and "db_user" set. * @param boolean $utf True if the database supports the UTF-8 character set. * * @return boolean|resource * * @since 2.0.0 * @throws \RuntimeException */ public function createDatabase($options, $utf = true) { if ($options === null) { throw new \RuntimeException('$options object must not be null.'); } if (empty($options->db_name)) { throw new \RuntimeException('$options object must have db_name set.'); } if (empty($options->db_user)) { throw new \RuntimeException('$options object must have db_user set.'); } $this->setQuery($this->getCreateDatabaseQuery($options, $utf)); return $this->execute(); } /** * Create a new DatabaseQuery object. * * @return QueryInterface * * @since 2.2 */ public function createQuery(): QueryInterface { return $this->factory->getQuery($this->name, $this); } /** * Disconnects the database. * * @return void * * @since 2.0.0 */ public function disconnect() { $this->freeResult(); $this->connection = null; $this->dispatchEvent(new ConnectionEvent(DatabaseEvents::POST_DISCONNECT, $this)); } /** * Dispatch an event. * * @param EventInterface $event The event to dispatch * * @return void * * @since 2.0.0 */ protected function dispatchEvent(EventInterface $event) { try { $this->getDispatcher()->dispatch($event->getName(), $event); } catch (\UnexpectedValueException $exception) { // Don't error if a dispatcher hasn't been set } } /** * Drops a table from the database. * * @param string $table The name of the database table to drop. * @param boolean $ifExists Optionally specify that the table must exist before it is dropped. * * @return $this * * @since 2.0.0 * @throws \RuntimeException */ public function dropTable($table, $ifExists = true) { $this->connect(); $this->setQuery('DROP TABLE ' . ($ifExists ? 'IF EXISTS ' : '') . $this->quoteName($table)) ->execute(); return $this; } /** * Execute the SQL statement. * * @return boolean * * @since 2.0.0 * @throws \RuntimeException */ public function execute() { $this->connect(); // Increment the query counter. $this->count++; // Get list of bound parameters $bounded =& $this->sql->getBounded(); // If there is a monitor registered, let it know we are starting this query if ($this->monitor) { // Take a local copy so that we don't modify the original query and cause issues later $sql = $this->replacePrefix((string) $this->sql); $this->monitor->startQuery($sql, $bounded); } // Execute the query. $this->executed = false; // Bind the variables foreach ($bounded as $key => $obj) { $this->statement->bindParam($key, $obj->value, $obj->dataType); } try { $this->executed = $this->statement->execute(); // If there is a monitor registered, let it know we have finished this query if ($this->monitor) { $this->monitor->stopQuery(); } return true; } catch (ExecutionFailureException $exception) { // If there is a monitor registered, let it know we have finished this query if ($this->monitor) { $this->monitor->stopQuery(); } // Check if the server was disconnected. if (!$this->connected()) { try { // Attempt to reconnect. $this->connection = null; $this->connect(); } catch (ConnectionFailureException $e) { // If connect fails, ignore that exception and throw the normal exception. throw $exception; } // Since we were able to reconnect, run the query again. return $this->execute(); } // Throw the normal query exception. throw $exception; } } /** * Method to fetch a row from the result set cursor as an array. * * @return mixed Either the next row from the result set or false if there are no more rows. * * @since 1.0 */ protected function fetchArray() { if ($this->statement) { return $this->statement->fetch(FetchMode::NUMERIC); } } /** * Method to fetch a row from the result set cursor as an associative array. * * @return mixed Either the next row from the result set or false if there are no more rows. * * @since 1.0 */ protected function fetchAssoc() { if ($this->statement) { return $this->statement->fetch(FetchMode::ASSOCIATIVE); } } /** * Method to fetch a row from the result set cursor as an object. * * Note, the fetch mode should be configured before calling this method using `StatementInterface::setFetchMode()`. * * @return mixed Either the next row from the result set or false if there are no more rows. * * @since 1.0 */ protected function fetchObject() { if ($this->statement) { return $this->statement->fetch(); } } /** * Method to free up the memory used for the result set. * * @return void * * @since 1.0 */ protected function freeResult() { $this->executed = false; if ($this->statement) { $this->statement->closeCursor(); } } /** * Get the number of affected rows for the previous executed SQL statement. * * @return integer The number of affected rows in the previous operation * * @since 2.0.0 */ public function getAffectedRows() { $this->connect(); if ($this->statement) { return $this->statement->rowCount(); } return 0; } /** * Method that provides access to the underlying database connection. * * @return resource The underlying database connection resource. * * @since 1.0 */ public function getConnection() { return $this->connection; } /** * Get the total number of SQL statements executed by the database driver. * * @return integer * * @since 1.0 */ public function getCount() { return $this->count; } /** * Return the query string to alter the database character set. * * @param string $dbName The database name * * @return string The query that alter the database query string * * @since 1.6.0 */ protected function getAlterDbCharacterSet($dbName) { return 'ALTER DATABASE ' . $this->quoteName($dbName) . ' CHARACTER SET ' . $this->quote('UTF8'); } /** * Return the query string to create new Database. * * @param \stdClass $options Object used to pass user and database name to database driver. This object must have "db_name" and "db_user" set. * @param boolean $utf True if the database supports the UTF-8 character set. * * @return string The query that creates database * * @since 2.0.0 */ protected function getCreateDatabaseQuery($options, $utf) { return 'CREATE DATABASE ' . $this->quoteName($options->db_name); } /** * Gets the name of the database used by this connection. * * @return string * * @since 1.0 */ protected function getDatabase() { return $this->database; } /** * Returns a PHP date() function compliant date format for the database driver. * * @return string * * @since 1.0 */ public function getDateFormat() { return 'Y-m-d H:i:s'; } /** * Get the minimum supported database version. * * @return string * * @since 1.0 */ public function getMinimum() { return static::$dbMinimum; } /** * Get the name of the database driver. * * If $this->name is not set it will try guessing the driver name from the class name. * * @return string * * @since 1.4.0 */ public function getName() { if (empty($this->name)) { $reflect = new \ReflectionClass($this); $this->name = strtolower(str_replace('Driver', '', $reflect->getShortName())); } return $this->name; } /** * Get the number of returned rows for the previous executed SQL statement. * * @return integer The number of returned rows. * * @since 2.0.0 */ public function getNumRows() { $this->connect(); if ($this->statement) { return $this->statement->rowCount(); } return 0; } /** * Get the server family type. * * If $this->serverType is not set it will attempt guessing the server family type from the driver name. If this is not possible the driver * name will be returned instead. * * @return string * * @since 1.4.0 */ public function getServerType() { if (empty($this->serverType)) { $name = $this->getName(); if (stristr($name, 'mysql') !== false) { $this->serverType = 'mysql'; } elseif (stristr($name, 'postgre') !== false) { $this->serverType = 'postgresql'; } elseif (stristr($name, 'pgsql') !== false) { $this->serverType = 'postgresql'; } elseif (stristr($name, 'oracle') !== false) { $this->serverType = 'oracle'; } elseif (stristr($name, 'sqlite') !== false) { $this->serverType = 'sqlite'; } elseif (stristr($name, 'sqlsrv') !== false) { $this->serverType = 'mssql'; } elseif (stristr($name, 'sqlazure') !== false) { $this->serverType = 'mssql'; } elseif (stristr($name, 'mssql') !== false) { $this->serverType = 'mssql'; } else { $this->serverType = $name; } } return $this->serverType; } /** * Get the null or zero representation of a timestamp for the database driver. * * @return string * * @since 1.0 */ public function getNullDate() { return $this->nullDate; } /** * Get the common table prefix for the database driver. * * @return string The common database table prefix. * * @since 1.0 */ public function getPrefix() { return $this->tablePrefix; } /** * Gets an exporter class object. * * @return DatabaseExporter An exporter object. * * @since 1.0 * @throws \RuntimeException */ public function getExporter() { return $this->factory->getExporter($this->name, $this); } /** * Gets an importer class object. * * @return DatabaseImporter * * @since 1.0 */ public function getImporter() { return $this->factory->getImporter($this->name, $this); } /** * Get the current query object or a new DatabaseQuery object. * * @param boolean $new False to return the current query object, True to return a new DatabaseQuery object. * The $new parameter is deprecated in 2.2 and will be removed in 4.0, use createQuery() instead. * * @return DatabaseQuery * * @since 1.0 */ public function getQuery($new = false) { if ($new) { trigger_deprecation( 'joomla/database', '2.2.0', 'The parameter $new is deprecated and will be removed in 4.0, use %s::createQuery() instead.', self::class ); return $this->createQuery(); } return $this->sql; } /** * Get a new iterator on the current query. * * @param string $column An option column to use as the iterator key. * @param string $class The class of object that is returned. * * @return DatabaseIterator * * @since 1.0 */ public function getIterator($column = null, $class = \stdClass::class) { if (!$this->executed) { $this->execute(); } /** * Calling setQuery free's the statement from the iterator which will break the iterator. * So we set statement to null so that freeResult on the statement here has no affect. * If you unset the iterator object then that will close the cursor and free the result. */ $iterator = $this->factory->getIterator($this->name, $this->statement, $column, $class); $this->statement = null; return $iterator; } /** * Shows the table CREATE statement that creates the given tables. * * @param mixed $tables A table name or a list of table names. * * @return array A list of the create SQL for the tables. * * @since 1.0 * @throws \RuntimeException */ abstract public function getTableCreate($tables); /** * Determine whether or not the database engine supports UTF-8 character encoding. * * @return boolean True if the database engine supports UTF-8 character encoding. * * @since 1.0 */ public function hasUtfSupport() { return $this->utf; } /** * Inserts a row into a table based on an object's properties. * * @param string $table The name of the database table to insert into. * @param object $object A reference to an object whose public properties match the table fields. * @param string $key The name of the primary key. If provided the object property is updated. * * @return boolean * * @since 1.0 * @throws \RuntimeException */ public function insertObject($table, &$object, $key = null) { $fields = []; $values = []; $tableColumns = $this->getTableColumns($table); // Iterate over the object variables to build the query fields and values. foreach (get_object_vars($object) as $k => $v) { // Skip columns that don't exist in the table. if (!\array_key_exists($k, $tableColumns)) { continue; } // Only process non-null scalars. if (\is_array($v) || \is_object($v) || $v === null) { continue; } // Ignore any internal fields. if ($k[0] === '_') { continue; } // Prepare and sanitize the fields and values for the database query. $fields[] = $this->quoteName($k); $values[] = $this->quote($v); } // Create the base insert statement. $query = $this->createQuery() ->insert($this->quoteName($table)) ->columns($fields) ->values(implode(',', $values)); // Set the query and execute the insert. $this->setQuery($query)->execute(); // Update the primary key if it exists. $id = $this->insertid(); if ($key && $id && \is_string($key)) { $object->$key = $id; } return true; } /** * Method to check whether the installed database version is supported by the database driver * * @return boolean True if the database version is supported * * @since 1.0 */ public function isMinimumVersion() { return version_compare($this->getVersion(), $this->getMinimum()) >= 0; } /** * Method to get the first row of the result set from the database query as an associative array of ['field_name' => 'row_value']. * * @return mixed The return value or null if the query failed. * * @since 1.0 * @throws \RuntimeException */ public function loadAssoc() { $this->connect(); $ret = null; // Execute the query and get the result set cursor. $this->execute(); // Get the first row from the result set as an associative array. $array = $this->fetchAssoc(); if ($array) { $ret = $array; } // Free up system resources and return. $this->freeResult(); return $ret; } /** * Method to get an array of the result set rows from the database query where each row is an associative array * of ['field_name' => 'row_value']. The array of rows can optionally be keyed by a field name, but defaults to * a sequential numeric array. * * NOTE: Choosing to key the result array by a non-unique field name can result in unwanted * behavior and should be avoided. * * @param string $key The name of a field on which to key the result array. * @param string $column An optional column name. Instead of the whole row, only this column value will be in * the result array. * * @return mixed The return value or null if the query failed. * * @since 1.0 * @throws \RuntimeException */ public function loadAssocList($key = null, $column = null) { $this->connect(); $array = []; // Execute the query and get the result set cursor. $this->execute(); // Get all of the rows from the result set. while ($row = $this->fetchAssoc()) { $value = $column ? ($row[$column] ?? $row) : $row; if ($key) { $array[$row[$key]] = $value; } else { $array[] = $value; } } // Free up system resources and return. $this->freeResult(); return $array; } /** * Method to get an array of values from the $offset field in each row of the result set from the database query. * * @param integer $offset The row offset to use to build the result array. * * @return mixed The return value or null if the query failed. * * @since 1.0 * @throws \RuntimeException */ public function loadColumn($offset = 0) { $this->connect(); $array = []; // Execute the query and get the result set cursor. $this->execute(); // Get all of the rows from the result set as arrays. while ($row = $this->fetchArray()) { $array[] = $row[$offset]; } // Free up system resources and return. $this->freeResult(); return $array; } /** * Method to get the first row of the result set from the database query as an object. * * @param string $class The class name to use for the returned row object. * * @return mixed The return value or null if the query failed. * * @since 1.0 * @throws \RuntimeException */ public function loadObject($class = \stdClass::class) { $this->connect(); $ret = null; if ($this->statement) { $fetchMode = $class === \stdClass::class ? FetchMode::STANDARD_OBJECT : FetchMode::CUSTOM_OBJECT; // PDO doesn't allow extra arguments for \PDO::FETCH_CLASS, so only forward the class for the custom object mode if ($fetchMode === FetchMode::STANDARD_OBJECT) { $this->statement->setFetchMode($fetchMode); } else { $this->statement->setFetchMode($fetchMode, $class); } } // Execute the query and get the result set cursor. $this->execute(); // Get the first row from the result set as an object of type $class. $object = $this->fetchObject(); if ($object) { $ret = $object; } // Free up system resources and return. $this->freeResult(); return $ret; } /** * Method to get an array of the result set rows from the database query where each row is an object. The array * of objects can optionally be keyed by a field name, but defaults to a sequential numeric array. * * NOTE: Choosing to key the result array by a non-unique field name can result in unwanted behavior and should be avoided. * * @param string $key The name of a field on which to key the result array. * @param string $class The class name to use for the returned row objects. * * @return mixed The return value or null if the query failed. * * @since 1.0 * @throws \RuntimeException */ public function loadObjectList($key = '', $class = \stdClass::class) { $this->connect(); $array = []; if ($this->statement) { $fetchMode = $class === \stdClass::class ? FetchMode::STANDARD_OBJECT : FetchMode::CUSTOM_OBJECT; // PDO doesn't allow extra arguments for \PDO::FETCH_CLASS, so only forward the class for the custom object mode if ($fetchMode === FetchMode::STANDARD_OBJECT) { $this->statement->setFetchMode($fetchMode); } else { $this->statement->setFetchMode($fetchMode, $class); } } // Execute the query and get the result set cursor. $this->execute(); // Get all of the rows from the result set as objects of type $class. while ($row = $this->fetchObject()) { if ($key) { $array[$row->$key] = $row; } else { $array[] = $row; } } // Free up system resources and return. $this->freeResult(); return $array; } /** * Method to get the first field of the first row of the result set from the database query. * * @return mixed The return value or null if the query failed. * * @since 1.0 * @throws \RuntimeException */ public function loadResult() { $this->connect(); $ret = null; // Execute the query and get the result set cursor. $this->execute(); // Get the first row from the result set as an array. $row = $this->fetchArray(); if ($row) { $ret = $row[0]; } // Free up system resources and return. $this->freeResult(); return $ret; } /** * Method to get the first row of the result set from the database query as an array. * * Columns are indexed numerically so the first column in the result set would be accessible via $row[0], etc. * * @return mixed The return value or null if the query failed. * * @since 1.0 * @throws \RuntimeException */ public function loadRow() { $this->connect(); $ret = null; // Execute the query and get the result set cursor. $this->execute(); // Get the first row from the result set as an array. $row = $this->fetchArray(); if ($row) { $ret = $row; } // Free up system resources and return. $this->freeResult(); return $ret; } /** * Method to get an array of the result set rows from the database query where each row is an array. The array * of objects can optionally be keyed by a field offset, but defaults to a sequential numeric array. * * NOTE: Choosing to key the result array by a non-unique field can result in unwanted behavior and should be avoided. * * @param string $key The name of a field on which to key the result array. * * @return array An array of results. * * @since 1.0 * @throws \RuntimeException */ public function loadRowList($key = null) { $this->connect(); $array = []; // Execute the query and get the result set cursor. $this->execute(); // Get all of the rows from the result set as arrays. while ($row = $this->fetchArray()) { if ($key !== null) { $array[$row[$key]] = $row; } else { $array[] = $row; } } // Free up system resources and return. $this->freeResult(); return $array; } /** * Prepares a SQL statement for execution * * @param string $query The SQL query to be prepared. * * @return StatementInterface * * @since 2.0.0 * @throws PrepareStatementFailureException */ abstract protected function prepareStatement(string $query): StatementInterface; /** * Alias for quote method * * @param array|string $text A string or an array of strings to quote. * @param boolean $escape True (default) to escape the string, false to leave it unchanged. * * @return string The quoted input string. * * @since 1.0 */ public function q($text, $escape = true) { return $this->quote($text, $escape); } /** * Quotes and optionally escapes a string to database requirements for use in database queries. * * @param array|string $text A string or an array of strings to quote. * @param boolean $escape True (default) to escape the string, false to leave it unchanged. * * @return array|string The quoted input string. * * @since 1.0 */ public function quote($text, $escape = true) { if (\is_array($text)) { foreach ($text as $k => $v) { $text[$k] = $this->quote($v, $escape); } return $text; } return '\'' . ($escape ? $this->escape($text) : $text) . '\''; } /** * Quotes a binary string to database requirements for use in database queries. * * @param string $data A binary string to quote. * * @return string The binary quoted input string. * * @since 1.7.0 */ public function quoteBinary($data) { // SQL standard syntax for hexadecimal literals return "X'" . bin2hex($data) . "'"; } /** * Replace special placeholder representing binary field with the original string. * * @param string|resource $data Encoded string or resource. * * @return string The original string. * * @since 1.7.0 */ public function decodeBinary($data) { return $data; } /** * Alias for quoteName method * * @param array|string $name The identifier name to wrap in quotes, or an array of identifier names to wrap in quotes. * Each type supports dot-notation name. * @param array|string $as The AS query part associated to $name. It can be string or array, in latter case it has to be * same length of $name; if is null there will not be any AS part for string or array element. * * @return array|string The quote wrapped name, same type of $name. * * @since 1.0 */ public function qn($name, $as = null) { return $this->quoteName($name, $as); } /** * Wrap an SQL statement identifier name such as column, table or database names in quotes to prevent injection * risks and reserved word conflicts. * * @param array|string $name The identifier name to wrap in quotes, or an array of identifier names to wrap in quotes. * Each type supports dot-notation name. * @param array|string $as The AS query part associated to $name. It can be string or array, in latter case it has to be * same length of $name; if is null there will not be any AS part for string or array element. * * @return array|string The quote wrapped name, same type of $name. * * @since 1.0 */ public function quoteName($name, $as = null) { if (\is_string($name)) { $name = $this->quoteNameString($name); if ($as !== null) { $name .= ' AS ' . $this->quoteNameString($as, true); } return $name; } $fin = []; if ($as === null) { foreach ($name as $str) { $fin[] = $this->quoteName($str); } } elseif (\is_array($name) && (\count($name) === \count($as))) { $count = \count($name); for ($i = 0; $i < $count; $i++) { $fin[] = $this->quoteName($name[$i], $as[$i]); } } return $fin; } /** * Quote string coming from quoteName call. * * @param string $name Identifier name to be quoted. * @param boolean $asSinglePart Treat the name as a single part of the identifier. * * @return string Quoted identifier string. * * @since 1.7.0 */ protected function quoteNameString($name, $asSinglePart = false) { $q = $this->nameQuote . $this->nameQuote; // Double quote reserved keyword $name = str_replace($q[1], $q[1] . $q[1], $name); if ($asSinglePart) { return $q[0] . $name . $q[1]; } return $q[0] . str_replace('.', "$q[1].$q[0]", $name) . $q[1]; } /** * Quote strings coming from quoteName call. * * @param array $strArr Array of strings coming from quoteName dot-explosion. * * @return string Dot-imploded string of quoted parts. * * @since 1.0 * @deprecated 2.0 Use quoteNameString instead */ protected function quoteNameStr($strArr) { $parts = []; $q = $this->nameQuote; foreach ($strArr as $part) { if ($part === null) { continue; } if (\strlen($q) === 1) { $parts[] = $q . $part . $q; } else { $parts[] = $q[0] . $part . $q[1]; } } return implode('.', $parts); } /** * This function replaces a string identifier with the configured table prefix. * * @param string $sql The SQL statement to prepare. * @param string $prefix The table prefix. * * @return string The processed SQL statement. * * @since 1.0 */ public function replacePrefix($sql, $prefix = '#__') { $escaped = false; $startPos = 0; $quoteChar = ''; $literal = ''; $sql = trim($sql); $n = \strlen($sql); while ($startPos < $n) { $ip = strpos($sql, $prefix, $startPos); if ($ip === false) { break; } $j = strpos($sql, "'", $startPos); $k = strpos($sql, '"', $startPos); if (($k !== false) && (($k < $j) || ($j === false))) { $quoteChar = '"'; $j = $k; } else { $quoteChar = "'"; } if ($j === false) { $j = $n; } $literal .= str_replace($prefix, $this->tablePrefix, substr($sql, $startPos, $j - $startPos)); $startPos = $j; $j = $startPos + 1; if ($j >= $n) { break; } // Quote comes first, find end of quote while (true) { $k = strpos($sql, $quoteChar, $j); $escaped = false; if ($k === false) { break; } $l = $k - 1; while ($l >= 0 && $sql[$l] === '\\') { $l--; $escaped = !$escaped; } if ($escaped) { $j = $k + 1; continue; } break; } if ($k === false) { // Error in the query - no end quote; ignore it break; } $literal .= substr($sql, $startPos, $k - $startPos + 1); $startPos = $k + 1; } if ($startPos < $n) { $literal .= substr($sql, $startPos, $n - $startPos); } return $literal; } /** * Get the query monitor. * * @return QueryMonitorInterface|null The query monitor or null if not set. * * @since 2.0.0 */ public function getMonitor() { return $this->monitor; } /** * Set a query monitor. * * @param QueryMonitorInterface|null $monitor The query monitor. * * @return $this * * @since 2.0.0 */ public function setMonitor(?QueryMonitorInterface $monitor = null) { $this->monitor = $monitor; return $this; } /** * Sets the SQL statement string for later execution. * * @param string|QueryInterface $query The SQL statement to set either as a Query object or a string. * @param integer $offset The affected row offset to set. {@deprecated 3.0 Use LimitableInterface::setLimit() instead} * @param integer $limit The maximum affected rows to set. {@deprecated 3.0 Use LimitableInterface::setLimit() instead} * * @return $this * * @since 1.0 * @throws \InvalidArgumentException */ public function setQuery($query, $offset = 0, $limit = 0) { $this->connect(); $this->freeResult(); if (\is_string($query)) { // Allows taking advantage of bound variables in a direct query: $query = $this->getQuery(true)->setQuery($query); } elseif (!($query instanceof QueryInterface)) { throw new \InvalidArgumentException( sprintf( 'A query must be a string or a %s instance, a %s was given.', QueryInterface::class, \gettype($query) === 'object' ? (\get_class($query) . ' instance') : \gettype($query) ) ); } if ($offset > 0 || $limit > 0) { trigger_deprecation( 'joomla/database', '2.0.0', 'The "$offset" and "$limit" arguments of %s() are deprecated and will be removed in 3.0, use %s::setLimit() instead.', __METHOD__, QueryInterface::class ); } // Check for values set on the query object and use those if there is a zero value passed here if ($limit === 0 && $query->limit > 0) { $limit = $query->limit; } if ($offset === 0 && $query->offset > 0) { $offset = $query->offset; } $query->setLimit($limit, $offset); $sql = $this->replacePrefix((string) $query); $this->statement = $this->prepareStatement($sql); $this->sql = $query; $this->limit = (int) max(0, $limit); $this->offset = (int) max(0, $offset); return $this; } /** * Set the connection to use UTF-8 character encoding. * * @return boolean True on success. * * @since 1.0 */ abstract public function setUtf(); /** * Method to truncate a table. * * @param string $table The table to truncate * * @return void * * @since 1.0 * @throws \RuntimeException */ public function truncateTable($table) { $this->setQuery('TRUNCATE TABLE ' . $this->quoteName($table)) ->execute(); } /** * Updates a row in a table based on an object's properties. * * @param string $table The name of the database table to update. * @param object $object A reference to an object whose public properties match the table fields. * @param array|string $key The name of the primary key. * @param boolean $nulls True to update null fields or false to ignore them. * * @return boolean True on success. * * @since 1.0 * @throws \RuntimeException */ public function updateObject($table, &$object, $key, $nulls = false) { $fields = []; $where = []; $tableColumns = $this->getTableColumns($table); if (\is_string($key)) { $key = [$key]; } if (\is_object($key)) { $key = (array) $key; } // Create the base update statement. $statement = 'UPDATE ' . $this->quoteName($table) . ' SET %s WHERE %s'; // Iterate over the object variables to build the query fields/value pairs. foreach (get_object_vars($object) as $k => $v) { // Skip columns that don't exist in the table. if (!\array_key_exists($k, $tableColumns)) { continue; } // Only process scalars that are not internal fields. if (\is_array($v) || \is_object($v) || $k[0] === '_') { continue; } // Set the primary key to the WHERE clause instead of a field to update. if (\in_array($k, $key, true)) { $where[] = $this->quoteName($k) . ($v === null ? ' IS NULL' : ' = ' . $this->quote($v)); continue; } // Prepare and sanitize the fields and values for the database query. if ($v === null) { // If the value is null and we want to update nulls then set it. if ($nulls) { $val = 'NULL'; } else { // If the value is null and we do not want to update nulls then ignore this field. continue; } } else { // The field is not null so we prep it for update. $val = $this->quote($v); } // Add the field to be updated. $fields[] = $this->quoteName($k) . '=' . $val; } // We don't have any fields to update. if (empty($fields)) { return true; } // Set the query and execute the update. $this->setQuery(sprintf($statement, implode(',', $fields), implode(' AND ', $where)))->execute(); return true; } } Attempted to load class "DatabaseDriver" from namespace "Joomla\Database". Did you forget a "use" statement for another namespace? (500 Whoops, looks like something went wrong.)

ClassNotFoundError

HTTP 500 Whoops, looks like something went wrong.

Attempted to load class "DatabaseDriver" from namespace "Joomla\Database".
Did you forget a "use" statement for another namespace?

Exception

Symfony\Component\ErrorHandler\Error\ ClassNotFoundError

  1.                     if (JDEBUG) {
  2.                         $options['monitor'] = new \Joomla\Database\Monitor\DebugMonitor();
  3.                     }
  4.                     try {
  5.                         $db DatabaseDriver::getInstance($options);
  6.                     } catch (\RuntimeException $e) {
  7.                         if (!headers_sent()) {
  8.                             header('HTTP/1.1 500 Internal Server Error');
  9.                         }
  1.     {
  2.         $callable $this->factory;
  3.         if ($this->isShared()) {
  4.             if ($this->instance === null) {
  5.                 $this->instance $callable($this->container);
  6.             }
  7.             return $this->instance;
  8.         }
  1.             }
  2.             throw new KeyNotFoundException(sprintf("Resource '%s' has not been registered with the container."$resourceName));
  3.         }
  4.         return $this->resources[$key]->getInstance();
  5.     }
  6.     /**
  7.      * Check if specified resource exists.
  8.      *
Container->get('Joomla\\Database\\DatabaseInterface') in /datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/src/Session/SessionFactory.php (line 63)
  1.                 }
  2.                 return new Handler\ApcuHandler();
  3.             case 'database':
  4.                 return new Handler\DatabaseHandler($this->getContainer()->get(DatabaseInterface::class));
  5.             case 'filesystem':
  6.             case 'none':
  7.                 // Try to use a custom configured path, fall back to the path in the PHP runtime configuration
  8.                 $path $config->get('session_filesystem_path'\ini_get('session.save_path'));
SessionFactory->createSessionHandler(array('force_ssl' => true, 'name' => 'b04a077b9675829ced6cf1d5809b76a6', 'expire' => 900)) in /datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/src/Service/Provider/Session.php (line 167)
  1.                 if ($config->get('force_ssl') == 2) {
  2.                     $options['force_ssl'] = true;
  3.                 }
  4.                 $handler $container->get('session.factory')->createSessionHandler($options);
  5.                 if (!$container->has('session.handler')) {
  6.                     $this->registerSessionHandlerAsService($container$handler);
  7.                 }
  1.     {
  2.         $callable $this->factory;
  3.         if ($this->isShared()) {
  4.             if ($this->instance === null) {
  5.                 $this->instance $callable($this->container);
  6.             }
  7.             return $this->instance;
  8.         }
  1.             }
  2.             throw new KeyNotFoundException(sprintf("Resource '%s' has not been registered with the container."$resourceName));
  3.         }
  4.         return $this->resources[$key]->getInstance();
  5.     }
  6.     /**
  7.      * Check if specified resource exists.
  8.      *
Container->get('Joomla\\Session\\SessionInterface') in /datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/src/Service/Provider/Application.php (line 104)
  1.                 'JApplicationSite',
  2.                 function (Container $container) {
  3.                     $app = new SiteApplication($container->get(CMSInput::class), $container->get('config'), null$container);
  4.                     $app->setDispatcher($container->get(DispatcherInterface::class));
  5.                     $app->setLogger($container->get(LoggerInterface::class));
  6.                     $app->setSession($container->get(SessionInterface::class));
  7.                     $app->setUserFactory($container->get(UserFactoryInterface::class));
  8.                     $app->setCacheControllerFactory($container->get(CacheControllerFactoryInterface::class));
  9.                     $app->setMenuFactory($container->get(MenuFactoryInterface::class));
  10.                     // Ensure that session purging is configured now we have a dispatcher
  1.     {
  2.         $callable $this->factory;
  3.         if ($this->isShared()) {
  4.             if ($this->instance === null) {
  5.                 $this->instance $callable($this->container);
  6.             }
  7.             return $this->instance;
  8.         }
  1.             }
  2.             throw new KeyNotFoundException(sprintf("Resource '%s' has not been registered with the container."$resourceName));
  3.         }
  4.         return $this->resources[$key]->getInstance();
  5.     }
  6.     /**
  7.      * Check if specified resource exists.
  8.      *
Container->get('Joomla\\CMS\\Application\\SiteApplication') in /datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/includes/app.php (line 52)
  1.     ->alias(\Joomla\CMS\Session\Session::class, 'session.web.site')
  2.     ->alias(\Joomla\Session\Session::class, 'session.web.site')
  3.     ->alias(\Joomla\Session\SessionInterface::class, 'session.web.site');
  4. // Instantiate the application.
  5. $app $container->get(\Joomla\CMS\Application\SiteApplication::class);
  6. // Set the application as global app
  7. \Joomla\CMS\Factory::$application $app;
  8. // Execute the application.
require_once('/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/includes/app.php') in /datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/index.php (line 32)
  1.  * define() is used rather than "const" to not error for PHP 5.2 and lower
  2.  */
  3. define('_JEXEC'1);
  4. // Run the application - All executable code should be triggered through this file
  5. require_once dirname(__FILE__) . '/includes/app.php';

Stack Trace

ClassNotFoundError
Symfony\Component\ErrorHandler\Error\ClassNotFoundError:
Attempted to load class "DatabaseDriver" from namespace "Joomla\Database".
Did you forget a "use" statement for another namespace?

  at /datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/src/Service/Provider/Database.php:123
  at Joomla\CMS\Service\Provider\Database->Joomla\CMS\Service\Provider\{closure}(object(Container))
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/vendor/joomla/di/src/ContainerResource.php:166)
  at Joomla\DI\ContainerResource->getInstance()
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/vendor/joomla/di/src/Container.php:95)
  at Joomla\DI\Container->get('Joomla\\Database\\DatabaseInterface')
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/src/Session/SessionFactory.php:63)
  at Joomla\CMS\Session\SessionFactory->createSessionHandler(array('force_ssl' => true, 'name' => 'b04a077b9675829ced6cf1d5809b76a6', 'expire' => 900))
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/src/Service/Provider/Session.php:167)
  at Joomla\CMS\Service\Provider\Session->Joomla\CMS\Service\Provider\{closure}(object(Container))
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/vendor/joomla/di/src/ContainerResource.php:166)
  at Joomla\DI\ContainerResource->getInstance()
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/vendor/joomla/di/src/Container.php:95)
  at Joomla\DI\Container->get('Joomla\\Session\\SessionInterface')
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/src/Service/Provider/Application.php:104)
  at Joomla\CMS\Service\Provider\Application->Joomla\CMS\Service\Provider\{closure}(object(Container))
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/vendor/joomla/di/src/ContainerResource.php:166)
  at Joomla\DI\ContainerResource->getInstance()
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/libraries/vendor/joomla/di/src/Container.php:95)
  at Joomla\DI\Container->get('Joomla\\CMS\\Application\\SiteApplication')
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/includes/app.php:52)
  at require_once('/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/includes/app.php')
     (/datas/yulpa173848/sites/samclap-ufolep.fr/htdocs/index.php:32)