+/6nAM+:iOK DIIl7M@5$^ @К6F= lKA7GFOfđ# bEA"Cv#༭ǴuSEρU۝яCa%*jY5>gDx~dB3 qJp-ݜ-q&ʌ@*!rHi0sAL GmEXGʔ}z\!ATv3{R!U+~Jܦу|!Fim^%vcBbҟ}:/궲=mZ#8i^凙D+2YXK g9M_쐮Ұmr&_BҲ 4ي.ܛg2jyBQ_Bڭ+N*O^ /.P$:|հQf֮όYsqcXְ{e66}M3~! ! Dx>8Mj cm7={m :CF/bW[?M~`AN_U~Xwb,"cEhN+dO )xWTL:x|]Vۦnh1Ѱ0*໻86̬eC!@+HnU|TziJe-1Y&n"X.i:fկZNYC@dSVcSKW}øU#_ő\4[y@.F y-E%S5Fd-I0i50$ذϋPܴIDhN>8*yE''U0([:}7ƓsNҪk]%Rpg.ImV6Gcּ!y(Bbem:oWVgd y~U-=z"hmZjwu+s6gܒcr]MwŢ0D[B( -PRX)'xGmoWWa)y~G€k#؊+e y:9 xc= b{n-GNh-⎈>eMVbyv?JόGi&*M0Er~F|ZUvܟDhķ l!$%M 3iJSjU7] OܰR-!5FO (;vSA3}}efCO*X;,&O/4ƑcvN?7߂1M:\uK%\h+c+G[GI^0DşZـ9 ɧm&VUKey+`Pk=+вCڰSi=тQu9y__wBUGfwy֟ Qj$E,+' }Yhp; 3M :ۇ"b 1z /ep9n,Sm2b|>m)4N*|o΀9:i//8WU'seiM)p2pseʀg(]/XF׏Ǎzv5 u3M2!Fָ pTpy^̷ NUuY0`VWJ[oyѡU&ի.KKhKY2w3_Z#S=8߹ F\+sv1mHfT>N `MڟZ)NZ%0^bV˳&WW7R;q3u۟@2N7:O24ۧsH. 'a넠._tR*En{}'S_Tgxr( Dۜ~X]@koJ#%E;(3XH~q^*fz%UB~nRd5ǯӈ 䳙q" ŬuJ{[Z2Z p_D&B$r>;a-2o<wl]r޺ٴzSd0njiu*_)Z57 iޔ}'9j. SAnlS"^+B79 dJ7؍94X^{³N.d/,?AmH6l=jLaWK8Ĉǒ'KB9I(طFT2~@.;Z|^_kc1YL=c%3"kՁ7^k;T4;8HcA'Gs->prepare($strQuery)->execute(); } /** * Execute a statement and return the number of affected rows * * @param string $strQuery The query string * * @return int The number of affected rows */ public function executeStatement(string $strQuery): int { return (int) $this->resConnection->executeStatement($strQuery); } /** * Execute a raw query and return a Result object * * @param string $strQuery The query string * * @return Result The Result object */ public function query($strQuery) { $objStatement = new Statement($this->resConnection); return $objStatement->query($strQuery); } /** * Auto-generate a FIND_IN_SET() statement * * @param string $strKey The field name * @param mixed $varSet The set to find the key in * @param boolean $blnIsField If true, the set will not be quoted * * @return string The FIND_IN_SET() statement */ public function findInSet($strKey, $varSet, $blnIsField=false) { if (\is_array($varSet)) { $varSet = implode(',', $varSet); } if ($blnIsField) { $varSet = static::quoteIdentifier($varSet); } else { $varSet = $this->resConnection->quote($varSet); } return "FIND_IN_SET(" . static::quoteIdentifier($strKey) . ", " . $varSet . ")"; } /** * Return all tables as array * * @param string $strDatabase The database name * @param boolean $blnNoCache If true, the cache will be bypassed * * @return array An array of table names */ public function listTables($strDatabase=null, $blnNoCache=false) { if ($blnNoCache || !isset($this->arrTablesCache[$strDatabase])) { $strOldDatabase = $this->resConnection->getDatabase(); // Change the database if ($strDatabase !== null && $strDatabase != $strOldDatabase) { $this->setDatabase($strDatabase); } $this->arrTablesCache[$strDatabase] = $this->resConnection->getSchemaManager()->listTableNames(); // Restore the database if ($strDatabase !== null && $strDatabase != $strOldDatabase) { $this->setDatabase($strOldDatabase); } } return $this->arrTablesCache[$strDatabase]; } /** * Determine if a particular database table exists * * @param string $strTable The table name * @param string $strDatabase The optional database name * @param boolean $blnNoCache If true, the cache will be bypassed * * @return boolean True if the table exists */ public function tableExists($strTable, $strDatabase=null, $blnNoCache=false) { if (!$strTable) { return false; } return \in_array($strTable, $this->listTables($strDatabase, $blnNoCache)); } /** * Return all columns of a particular table as array * * @param string $strTable The table name * @param boolean $blnNoCache If true, the cache will be bypassed * * @return array An array of column names */ public function listFields($strTable, $blnNoCache=false) { if ($blnNoCache || !isset($this->arrCache[$strTable])) { $arrReturn = array(); $objFields = $this->query("SHOW FULL COLUMNS FROM $strTable"); while ($objFields->next()) { $arrTmp = array(); $arrChunks = preg_split('/(\([^)]+\))/', $objFields->Type, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY); $arrTmp['name'] = $objFields->Field; $arrTmp['type'] = $arrChunks[0]; if (!empty($arrChunks[1])) { $arrChunks[1] = str_replace(array('(', ')'), '', $arrChunks[1]); // Handle enum fields (see #6387) if ($arrChunks[0] == 'enum') { $arrTmp['length'] = $arrChunks[1]; } else { $arrSubChunks = explode(',', $arrChunks[1]); $arrTmp['length'] = trim($arrSubChunks[0]); if (!empty($arrSubChunks[1])) { $arrTmp['precision'] = trim($arrSubChunks[1]); } } } if (!empty($arrChunks[2])) { $arrTmp['attributes'] = trim($arrChunks[2]); } if ($objFields->Key) { switch ($objFields->Key) { case 'PRI': $arrTmp['index'] = 'PRIMARY'; break; case 'UNI': $arrTmp['index'] = 'UNIQUE'; break; case 'MUL': // Ignore break; default: $arrTmp['index'] = 'KEY'; break; } } // Do not modify the order! $arrTmp['collation'] = $objFields->Collation; $arrTmp['null'] = ($objFields->Null == 'YES') ? 'NULL' : 'NOT NULL'; $arrTmp['default'] = $objFields->Default; $arrTmp['extra'] = $objFields->Extra; $arrTmp['origtype'] = $objFields->Type; $arrReturn[] = $arrTmp; } $objIndex = $this->query("SHOW INDEXES FROM `$strTable`"); while ($objIndex->next()) { $strColumnName = $objIndex->Column_name; if ($objIndex->Sub_part) { $strColumnName .= '(' . $objIndex->Sub_part . ')'; } $arrReturn[$objIndex->Key_name]['name'] = $objIndex->Key_name; $arrReturn[$objIndex->Key_name]['type'] = 'index'; $arrReturn[$objIndex->Key_name]['index_fields'][] = $strColumnName; $arrReturn[$objIndex->Key_name]['index'] = (($objIndex->Non_unique == 0) ? 'UNIQUE' : 'KEY'); } $this->arrCache[$strTable] = $arrReturn; } return $this->arrCache[$strTable]; } /** * Determine if a particular column exists * * @param string $strField The field name * @param string $strTable The table name * @param boolean $blnNoCache If true, the cache will be bypassed * * @return boolean True if the field exists */ public function fieldExists($strField, $strTable, $blnNoCache=false) { if (!$strField || !$strTable) { return false; } foreach ($this->listFields($strTable, $blnNoCache) as $arrField) { if ($arrField['name'] == $strField && $arrField['type'] != 'index') { return true; } } return false; } /** * Determine if a particular index exists * * @param string $strName The index name * @param string $strTable The table name * @param boolean $blnNoCache If true, the cache will be bypassed * * @return boolean True if the index exists */ public function indexExists($strName, $strTable, $blnNoCache=false) { if (!$strName || !$strTable) { return false; } foreach ($this->listFields($strTable, $blnNoCache) as $arrField) { if ($arrField['name'] == $strName && $arrField['type'] == 'index') { return true; } } return false; } /** * Return the field names of a particular table as array * * @param string $strTable The table name * @param boolean $blnNoCache If true, the cache will be bypassed * * @return array An array of field names */ public function getFieldNames($strTable, $blnNoCache=false) { $arrNames = array(); $arrFields = $this->listFields($strTable, $blnNoCache); foreach ($arrFields as $arrField) { if ($arrField['type'] != 'index') { $arrNames[] = $arrField['name']; } } return $arrNames; } /** * Check whether a field value in the database is unique * * @param string $strTable The table name * @param string $strField The field name * @param mixed $varValue The field value * @param integer $intId The ID of a record to exempt * * @return boolean True if the field value is unique */ public function isUniqueValue($strTable, $strField, $varValue, $intId=null) { $strQuery = "SELECT * FROM $strTable WHERE " . static::quoteIdentifier($strField) . "=?"; if ($intId !== null) { $strQuery .= " AND id!=?"; } $objUnique = $this->prepare($strQuery) ->limit(1) ->execute($varValue, $intId); return $objUnique->numRows ? false : true; } /** * Return the IDs of all child records of a particular record (see #2475) * * @param mixed $arrParentIds An array of parent IDs * @param string $strTable The table name * @param boolean $blnSorting True if the table has a sorting field * @param array $arrReturn The array to be returned * @param string $strWhere Additional WHERE condition * * @return array An array of child record IDs */ public function getChildRecords($arrParentIds, $strTable, $blnSorting=false, $arrReturn=array(), $strWhere='') { if (!\is_array($arrParentIds)) { $arrParentIds = array($arrParentIds); } // Remove zero IDs $arrParentIds = array_filter(array_map('\intval', $arrParentIds)); if (empty($arrParentIds)) { return $arrReturn; } $objChilds = $this->query("SELECT id, pid FROM " . $strTable . " WHERE pid IN(" . implode(',', $arrParentIds) . ")" . ($strWhere ? " AND $strWhere" : "") . ($blnSorting ? " ORDER BY " . $this->findInSet('pid', $arrParentIds) . ", sorting" : "")); if ($objChilds->numRows > 0) { if ($blnSorting) { $arrChilds = array(); $arrOrdered = array(); while ($objChilds->next()) { $arrChilds[] = $objChilds->id; $arrOrdered[$objChilds->pid][] = $objChilds->id; } foreach (array_reverse(array_keys($arrOrdered)) as $pid) { $pos = (int) array_search($pid, $arrReturn); ArrayUtil::arrayInsert($arrReturn, $pos+1, $arrOrdered[$pid]); } $arrReturn = $this->getChildRecords($arrChilds, $strTable, $blnSorting, $arrReturn, $strWhere); } else { $arrChilds = $objChilds->fetchEach('id'); $arrReturn = array_merge($arrChilds, $this->getChildRecords($arrChilds, $strTable, $blnSorting, $arrReturn, $strWhere)); } } return array_map('\intval', $arrReturn); } /** * Return the IDs of all parent records of a particular record * * @param integer $intId The ID of the record * @param string $strTable The table name * @param bool $skipId Omit the provided ID in the result set * * @return array An array of parent record IDs */ public function getParentRecords($intId, $strTable, bool $skipId = false) { // Limit to a nesting level of 10 $ids = $this->prepare("SELECT id, @pid:=pid FROM $strTable WHERE id=?" . str_repeat(" UNION SELECT id, @pid:=pid FROM $strTable WHERE id=@pid", 9)) ->execute($intId) ->fetchEach('id'); // Trigger recursion in case our query returned exactly 10 IDs in which case we might have higher parent records if (\count($ids) === 10) { $ids = array_merge($ids, $this->getParentRecords(end($ids), $strTable, true)); } if ($skipId && ($key = array_search($intId, $ids)) !== false) { unset($ids[$key]); } return array_map('\intval', array_values($ids)); } /** * Change the current database * * @param string $strDatabase The name of the target database */ public function setDatabase($strDatabase) { $this->resConnection->executeStatement("USE $strDatabase"); } /** * Begin a transaction */ public function beginTransaction() { $this->resConnection->beginTransaction(); } /** * Commit a transaction */ public function commitTransaction() { $this->resConnection->commit(); } /** * Rollback a transaction */ public function rollbackTransaction() { $this->resConnection->rollBack(); } /** * Lock one or more tables * * @param array $arrTables An array of table names to be locked */ public function lockTables($arrTables) { $arrLocks = array(); foreach ($arrTables as $table=>$mode) { $arrLocks[] = $this->resConnection->quoteIdentifier($table) . ' ' . $mode; } $this->resConnection->executeStatement('LOCK TABLES ' . implode(', ', $arrLocks) . ';'); } /** * Unlock all tables */ public function unlockTables() { $this->resConnection->executeStatement('UNLOCK TABLES;'); } /** * Return the table size in bytes * * @param string $strTable The table name * * @return integer The table size in bytes */ public function getSizeOf($strTable) { try { // MySQL 8 compatibility $this->resConnection->executeStatement('SET @@SESSION.information_schema_stats_expiry = 0'); } catch (DriverException $e) { } $status = $this->resConnection->fetchAssociative('SHOW TABLE STATUS LIKE ' . $this->resConnection->quote($strTable)); return $status['Data_length'] + $status['Index_length']; } /** * Return the next autoincrement ID of a table * * @param string $strTable The table name * * @return integer The autoincrement ID */ public function getNextId($strTable) { try { // MySQL 8 compatibility $this->resConnection->executeStatement('SET @@SESSION.information_schema_stats_expiry = 0'); } catch (DriverException $e) { } $status = $this->resConnection->fetchAssociative('SHOW TABLE STATUS LIKE ' . $this->resConnection->quote($strTable)); return $status['Auto_increment']; } /** * Return a universal unique identifier * * @return string The UUID string */ public function getUuid() { static $ids; if (empty($ids)) { $ids = $this->resConnection->fetchFirstColumn(implode(' UNION ALL ', array_fill(0, 10, "SELECT UNHEX(REPLACE(UUID(), '-', '')) AS uuid"))); } return array_pop($ids); } /** * Quote the column name if it is a reserved word * * @param string $strName * * @return string */ public static function quoteIdentifier($strName) { // Quoted already or not an identifier (AbstractPlatform::quoteIdentifier() handles table.column so also allow . here) if (!preg_match('/^[A-Za-z0-9_$.]+$/', $strName)) { return $strName; } return System::getContainer()->get('database_connection')->quoteIdentifier($strName); } /** * Execute a query and do not cache the result * * @param string $strQuery The query string * * @return Result The Result object * * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0. * Use Database::execute() instead. */ public function executeUncached($strQuery) { trigger_deprecation('contao/core-bundle', '4.0', 'Using "Contao\Database::executeUncached()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Database::execute()" instead.'); return $this->execute($strQuery); } /** * Always execute the query and add or replace an existing cache entry * * @param string $strQuery The query string * * @return Result The Result object * * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0. * Use Database::execute() instead. */ public function executeCached($strQuery) { trigger_deprecation('contao/core-bundle', '4.0', 'Using "Contao\Database::executeCached()" has been deprecated and will no longer work in Contao 5.0. Use "Contao\Database::execute()" instead.'); return $this->execute($strQuery); } } class_alias(Database::class, 'Database'); An Error Occurred: Internal Server Error

Oops! An Error Occurred

The server returned a "500 Internal Server Error".

Something is broken. Please let us know what you were doing when this error occurred. We will fix it as soon as possible. Sorry for any inconvenience caused.