public static function setUpBeforeClass()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     if (DB_TYPE == 'sqlite') {
         $db->execute(file_get_contents(DB_SETUP_FILE));
         $db->execute(file_get_contents(DB_EXTENDED_SETUP_FILE));
     }
     $db->execute(file_get_contents(DB_POPULATE_FILE));
     $db->execute(file_get_contents(DB_EXTENDED_POPULATE_FILE));
     self::$db = $db;
     self::$schema = new fSchema($db);
     fORMDatabase::attach(self::$db);
     fORMSchema::attach(self::$schema);
     fORMOrdering::configureOrderingColumn('TopAlbum', 'position');
     fORMOrdering::configureOrderingColumn('FavoriteAlbum', 'position');
     fORMOrdering::configureOrderingColumn('YearFavoriteAlbum', 'position');
     if (defined('MAP_TABLES')) {
         fORM::mapClassToTable('User', 'user');
         fORM::mapClassToTable('Group', 'group');
         fORM::mapClassToTable('Artist', 'popular_artists');
         fORM::mapClassToTable('Album', 'records');
     }
 }
Example #2
0
 protected function setUp()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     $db->execute(file_get_contents(DB_SETUP_FILE));
     $this->sharedFixture = $db;
 }
Example #3
0
 public static function setUpBeforeClass()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     $db->execute(file_get_contents(DB_SETUP_FILE));
     self::$db = $db;
 }
Example #4
0
 protected function setUp()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     $db->execute(file_get_contents(DB_SETUP_FILE));
     $this->sharedFixture = array('db' => $db, 'schema' => fJSON::decode(file_get_contents(DB_SCHEMA_FILE), TRUE));
 }
 public static function setUpBeforeClass()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     $db->execute(file_get_contents(DB_SETUP_FILE));
     $db->execute(fix_schema(file_get_contents(DB_ALTERNATE_SCHEMA_SETUP_FILE)));
     self::$db = $db;
     self::$schema = fJSON::decode(fix_schema(file_get_contents(DB_ALTERNATE_SCHEMA_SCHEMA_FILE)), TRUE);
 }
Example #6
0
 protected function setUp()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     $db->execute(file_get_contents(DB_SETUP_FILE));
     $db->execute(file_get_contents(DB_EXTENDED_SETUP_FILE));
     $schema = new fSchema($db);
     $this->sharedFixture = array('db' => $db, 'schema' => $schema);
 }
 public static function setUpBeforeClass()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     if (DB_TYPE == 'sqlite') {
         $db->execute(file_get_contents(DB_SETUP_FILE));
         $db->execute(file_get_contents(DB_EXTENDED_SETUP_FILE));
     }
     $db->execute(file_get_contents(DB_POPULATE_FILE));
     self::$db = $db;
     self::$json_schema = fJSON::decode(file_get_contents(DB_SCHEMA_FILE), TRUE);
 }
 protected function setUp()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     $db->execute(file_get_contents(DB_SETUP_FILE));
     $db2 = new fDatabase(DB_TYPE, DB_2, DB_2_USERNAME, DB_2_PASSWORD, DB_2_HOST, DB_2_PORT);
     $db2->execute(file_get_contents(DB_2_SETUP_FILE));
     $this->sharedFixture = array($db, $db2);
     fORMDatabase::attach($db);
     fORMDatabase::attach($db2, 'db2');
     fORM::mapClassToTable('Db2User', 'users');
     fORM::mapClassToDatabase('Db2User', 'db2');
     fORM::mapClassToTable('Db2Group', 'groups');
     fORM::mapClassToDatabase('Db2Group', 'db2');
 }
Example #9
0
 /**
  * The MySQL PDO driver has issues if you try to reuse a prepared statement
  * without any placeholders.
  * 
  * @return void
  */
 private function regenerateStatement()
 {
     $is_pdo = $this->database->getExtension() == 'pdo';
     $is_mysql = $this->database->getType() == 'mysql';
     if ($this->placeholders || !$is_pdo || !$is_mysql) {
         return;
     }
     $this->statement = $this->database->getConnection()->prepare($this->sql);
 }
 public static function setUpBeforeClass()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     $db->execute(file_get_contents(DB_SETUP_FILE));
     $db2 = new fDatabase(DB_TYPE, DB_2, DB_2_USERNAME, DB_2_PASSWORD, DB_2_HOST, DB_2_PORT);
     $db2->execute(file_get_contents(DB_2_SETUP_FILE));
     self::$db = $db;
     self::$db2 = $db2;
     fORMDatabase::attach($db);
     fORMDatabase::attach($db2, 'db2');
     fORM::mapClassToTable('Db2User', 'users');
     fORM::mapClassToDatabase('Db2User', 'db2');
     fORM::mapClassToTable('Db2Group', 'groups');
     fORM::mapClassToDatabase('Db2Group', 'db2');
 }
 public static function setUpBeforeClass()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     if (DB_TYPE == 'sqlite') {
         $db->execute(file_get_contents(DB_SETUP_FILE));
     }
     $db->execute(file_get_contents(DB_POPULATE_FILE));
     self::$db = $db;
     $db2 = new fDatabase(DB_TYPE, DB_2, DB_2_USERNAME, DB_2_PASSWORD, DB_2_HOST, DB_2_PORT);
     if (DB_TYPE == 'sqlite') {
         $db2->execute(file_get_contents(DB_2_SETUP_FILE));
     }
     $db2->execute(file_get_contents(DB_2_POPULATE_FILE));
     self::$db2 = $db2;
     self::$schema = new fSchema($db);
     self::$schema2 = new fSchema($db2);
 }
Example #12
0
 /**
  * Creates a unique cache prefix to help prevent cache conflicts
  * 
  * @return void
  */
 private function makeCachePrefix()
 {
     $prefix = 'fSchema::' . $this->database->getType() . '::';
     if ($this->database->getHost()) {
         $prefix .= $this->database->getHost() . '::';
     }
     if ($this->database->getPort()) {
         $prefix .= $this->database->getPort() . '::';
     }
     $prefix .= $this->database->getDatabase() . '::';
     if ($this->database->getUsername()) {
         $prefix .= $this->database->getUsername() . '::';
     }
     return $prefix;
 }
Example #13
0
 /**
  * Decodes national (unicode) character data coming out of MSSQL into UTF-8
  * 
  * @param  array $row  The row from the database
  * @return array  The fixed row
  */
 private function decodeMSSQLNationalColumns($row)
 {
     if (strpos($this->sql, 'fmssqln__') === FALSE) {
         return $row;
     }
     $columns = array_keys($row);
     foreach ($columns as $column) {
         if (substr($column, 0, 9) != 'fmssqln__') {
             continue;
         }
         $real_column = substr($column, 9);
         $row[$real_column] = iconv('ucs-2le', 'utf-8', $this->database->unescape('blob', $row[$column]));
         unset($row[$column]);
     }
     return $row;
 }
 public static function setUpBeforeClass()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     if (DB_TYPE == 'sqlite') {
         $db->execute(file_get_contents(DB_SETUP_FILE));
         $db->execute(file_get_contents(DB_EXTENDED_SETUP_FILE));
         $db->execute(fix_schema(file_get_contents(DB_ALTERNATE_SCHEMA_SETUP_FILE)));
     }
     $db->execute(file_get_contents(DB_POPULATE_FILE));
     $db->execute(file_get_contents(DB_EXTENDED_POPULATE_FILE));
     $db->execute(fix_schema(file_get_contents(DB_ALTERNATE_SCHEMA_POPULATE_FILE)));
     $db->clearCache();
     fORMDatabase::attach($db);
     self::$db = $db;
     fORM::mapClassToTable('Flourish2User', fix_schema('flourish2.users'));
     fORM::mapClassToTable('Flourish2Group', fix_schema('flourish2.groups'));
     fORM::mapClassToTable('Flourish2Artist', fix_schema('flourish2.artists'));
     fORM::mapClassToTable('Flourish2Album', fix_schema('flourish2.albums'));
 }
Example #15
0
 /** 
  * Seeks to the specified zero-based row for the specified SQL query
  * 
  * @throws fNoRowsException  When the query did not return any rows
  * 
  * @param  integer $row  The row number to seek to (zero-based)
  * @return void
  */
 public function seek($row)
 {
     if (!$this->returned_rows) {
         throw new fNoRowsException('The query did not return any rows');
     }
     if ($row >= $this->returned_rows || $row < 0) {
         throw new fProgrammerException('The row requested does not exist');
     }
     $this->pointer = $row;
     switch ($this->database->getExtension()) {
         case 'mssql':
             $success = mssql_data_seek($this->result, $row);
             break;
         case 'mysql':
             $success = mysql_data_seek($this->result, $row);
             break;
         case 'mysqli':
             if (is_object($this->result)) {
                 $success = mysqli_data_seek($this->result, $row);
             } else {
                 $success = TRUE;
             }
             break;
         case 'pgsql':
             $success = pg_result_seek($this->result, $row);
             break;
         case 'sqlite':
             $success = sqlite_seek($this->result, $row);
             break;
         case 'ibm_db2':
         case 'oci8':
         case 'odbc':
         case 'pdo':
         case 'sqlsrv':
             // Do nothing since we already changed the pointer
             $success = TRUE;
             break;
     }
     if (!$success) {
         throw new fSQLException('There was an error seeking to row %s', $row);
     }
     $this->advanceCurrentRow();
 }
 public static function setUpBeforeClass()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     if (DB_TYPE == 'sqlite') {
         $db->execute(file_get_contents(DB_SETUP_FILE));
         $db->execute(file_get_contents(DB_EXTENDED_SETUP_FILE));
     }
     $db->execute(file_get_contents(DB_POPULATE_FILE));
     $db->execute(file_get_contents(DB_EXTENDED_POPULATE_FILE));
     fORMDatabase::attach($db);
     self::$db = $db;
 }
 protected function setUp()
 {
     if (defined('SKIPPING')) {
         return;
     }
     $db = new fDatabase(DB_TYPE, DB, DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT);
     $db->execute(file_get_contents(DB_SETUP_FILE));
     $db->execute(file_get_contents(DB_EXTENDED_SETUP_FILE));
     $db->execute(fix_schema(file_get_contents(DB_ALTERNATE_SCHEMA_SETUP_FILE)));
     $db->clearCache();
     fORMDatabase::attach($db);
     $this->sharedFixture = $db;
     fORM::mapClassToTable('Flourish2User', fix_schema('flourish2.users'));
     fORM::mapClassToTable('Flourish2Group', fix_schema('flourish2.groups'));
     fORM::mapClassToTable('Flourish2Artist', fix_schema('flourish2.artists'));
     fORM::mapClassToTable('Flourish2Album', fix_schema('flourish2.albums'));
 }
Example #18
0
<?php

/**
 * Prepares classes and database for tests.
 */
// Some basics
date_default_timezone_set('Europe/Copenhagen');
define("FIXTURES_ROOT", dirname(__FILE__) . '/fixtures/');
include dirname(__FILE__) . '/flourish/fLoader.php';
fLoader::best();
// Include fFixture
include dirname(__FILE__) . '/../fFixture.php';
include dirname(__FILE__) . '/../fFixtureSeed.php';
// Emtpy database
$db = new fDatabase('sqlite', dirname(__FILE__) . '/test.db');
$db_setup_file = new fFile(dirname(__FILE__) . '/bootstrap.sql');
define("RESET_DATABASE_SQL", $db_setup_file->read());
$db->execute(RESET_DATABASE_SQL);
// Setup ORM
fORMDatabase::attach($db);
// Pretend implementations of fActiveRecord
class Category extends fActiveRecord
{
}
class Product extends fActiveRecord
{
}
class Shop extends fActiveRecord
{
}
class User extends fActiveRecord
 /**
  * Translates Flourish SQL `ALTER TABLE * RENAME TO` statements to the appropriate
  * statements for SQLite
  *
  * @param string $sql                The SQL statements that will be executed against the database
  * @param array  &$extra_statements  Any extra SQL statements required for SQLite
  * @param array  $data               Data parsed from the `ALTER TABLE` statement
  * @return string  The modified SQL statement
  */
 private function translateSQLiteRenameTableStatements($sql, &$extra_statements, $data)
 {
     $tables = $this->getSQLiteTables();
     if (in_array($data['new_table_name'], $tables)) {
         $this->throwException(self::compose('A table with the name "%1$s" already exists', $data['new_table_name']), $sql);
     }
     if (!in_array($data['table'], $tables)) {
         $this->throwException(self::compose('The table specified, "%1$s", does not exist', $data['table']), $sql);
     }
     // We start by dropping all references to this table
     $foreign_keys = $this->getSQLiteForeignKeys($data['table']);
     foreach ($foreign_keys as $foreign_key) {
         $extra_statements = array_merge($extra_statements, $this->database->preprocess("ALTER TABLE %r DROP FOREIGN KEY (%r)", array($foreign_key['table'], $foreign_key['column']), TRUE));
     }
     // SQLite 2 does not natively support renaming tables, so we have to do
     // it by creating a new table name and copying all data and indexes
     if (version_compare($this->database->getVersion(), 3, '<')) {
         $renamed_create_sql = preg_replace('#^\\s*CREATE\\s+TABLE\\s+["\\[`\']?\\w+["\\]`\']?\\s+#i', 'CREATE TABLE "' . $data['new_table_name'] . '" ', $this->getSQLiteCreateTable($data['table']));
         $this->addSQLiteTable($data['new_table_name'], $renamed_create_sql);
         // We rename string placeholders to prevent confusion with
         // string placeholders that are added by call to fDatabase
         $renamed_create_sql = str_replace(':string_', ':sub_string_', $renamed_create_sql);
         $create_statements = str_replace(':sub_string_', ':string_', $this->database->preprocess($renamed_create_sql, array(), TRUE));
         $extra_statements[] = array_shift($create_statements);
         // Recreate the indexes on the new table
         $indexes = $this->getSQLiteIndexes($data['table']);
         foreach ($indexes as $name => $index) {
             $create_sql = $index['sql'];
             preg_match('#^\\s*CREATE\\s+(?:UNIQUE\\s+)?INDEX\\s+(?:[\'"`\\[]?\\w+[\'"`\\]]?\\.)?[\'"`\\[]?\\w+[\'"`\\]]?\\s+(ON\\s+[\'"`\\[]?\\w+[\'"`\\]]?)\\s*(\\((\\s*(?:\\s*[\'"`\\[]?\\w+[\'"`\\]]?\\s*,\\s*)*[\'"`\\[]?\\w+[\'"`\\]]?\\s*)\\))\\s*$#Di', $create_sql, $match);
             // Fix the table name to the new table
             $create_sql = str_replace($match[1], preg_replace('#(?:`|\'|"|\\[|\\b)?' . preg_quote($data['table'], '#') . '(?:`|\'|"|\\]|\\b)?#i', '"' . $data['new_table_name'] . '"', $match[1]), $create_sql);
             // We change the name of the index to keep it in sync
             // with the new table name
             $new_name = preg_replace('#^' . preg_quote($data['table'], '#') . '_#i', $data['new_table_name'] . '_', $name);
             $create_sql = preg_replace('#[\'"`\\[]?' . preg_quote($name, '#') . '[\'"`\\]]?(\\s+ON\\s+)#i', '"' . $new_name . '"\\1', $create_sql);
             $extra_statements[] = $create_sql;
             $this->addSQLiteIndex($new_name, $data['new_table_name'], $create_sql);
         }
         $column_names = $this->getSQLiteColumns($data['table']);
         $extra_statements[] = $this->database->escape("INSERT INTO %r (%r) SELECT %r FROM %r", $data['new_table_name'], $column_names, $column_names, $data['table']);
         $extra_statements = array_merge($extra_statements, $create_statements);
         $extra_statements = array_merge($extra_statements, $this->database->preprocess("DROP TABLE %r", array($data['table']), TRUE));
         // SQLite 3 natively supports renaming tables, but it does not fix
         // references to the old table name inside of trigger bodies
     } else {
         // We add the rename SQL in the middle so it happens after we drop the
         // foreign key constraints and before we re-add them
         $extra_statements[] = $sql;
         $this->addSQLiteTable($data['new_table_name'], preg_replace('#^\\s*CREATE\\s+TABLE\\s+[\'"\\[`]?\\w+[\'"\\]`]?\\s+#i', 'CREATE TABLE "' . $data['new_table_name'] . '" ', $this->getSQLiteCreateTable($data['table'])));
         $this->removeSQLiteTable($data['table']);
         // Copy the trigger definitions to the new table name
         foreach ($this->getSQLiteTriggers() as $name => $trigger) {
             if ($trigger['table'] == $data['table']) {
                 $this->addSQLiteTrigger($name, $data['new_table_name'], $trigger['sql']);
             }
         }
         // Move the index definitions to the new table name
         foreach ($this->getSQLiteIndexes($data['table']) as $name => $index) {
             $this->addSQLiteIndex($name, $data['new_table_name'], preg_replace('#(\\s+ON\\s+)["\'`\\[]?\\w+["\'`\\]]?#', '\\1"' . preg_quote($data['new_table_name'], '#') . '"', $index['sql']));
         }
         foreach ($this->getSQLiteTriggers() as $name => $trigger) {
             $create_sql = $trigger['sql'];
             $create_sql = preg_replace('#( on table )"' . $data['table'] . '"#i', '\\1"' . $data['new_table_name'] . '"', $create_sql);
             $create_sql = preg_replace('#(\\s+FROM\\s+)(`' . $data['table'] . '`|"' . $data['table'] . '"|\'' . $data['table'] . '\'|' . $data['table'] . '|\\[' . $data['table'] . '\\])#i', '\\1"' . $data['new_table_name'] . '"', $create_sql);
             if ($create_sql != $trigger['sql']) {
                 $extra_statements[] = $this->database->escape("DROP TRIGGER %r", $name);
                 $this->removeSQLiteTrigger($name);
                 $this->addSQLiteTrigger($name, $data['new_table_name'], $create_sql);
                 $extra_statements[] = $create_sql;
             }
         }
     }
     // Here we recreate the references that we dropped at the beginning
     foreach ($foreign_keys as $foreign_key) {
         $extra_statements = array_merge($extra_statements, $this->database->preprocess("ALTER TABLE %r ADD FOREIGN KEY (%r) REFERENCES %r(%r) ON UPDATE " . $foreign_key['on_update'] . " ON DELETE " . $foreign_key['on_delete'], array($foreign_key['table'], $foreign_key['column'], $data['new_table_name'], $foreign_key['foreign_column']), TRUE));
     }
     // Remove any nested transactions
     $extra_statements = array_diff($extra_statements, array("BEGIN", "COMMIT"));
     // Since the actual rename or create/drop has to happen after adjusting
     // foreign keys, we previously added it in the appropriate place and
     // now need to provide the first statement to be run
     return array_shift($extra_statements);
 }
 /**
  * Translates `LIMIT x OFFSET x` to `ROW_NUMBER() OVER (ORDER BY)` syntax
  * 
  * @param  string $sql  The SQL to translate
  * @return string  The translated SQL
  */
 private function translateLimitOffsetToRowNumber($sql)
 {
     // Regex details:
     // 1 - The SELECT clause
     // 2 - () recursion handler
     // 3 - FROM clause
     // 4 - () recursion handler
     // 5 - ORDER BY clause
     // 6 - () recursion handler
     // 7 - LIMIT number
     // 8 - OFFSET number
     preg_match_all('#select((?:(?:(?!\\sfrom\\s)[^()])+|\\(((?:[^()]+|\\((?2)\\))*)\\))*\\s)(from(?:(?:(?!\\slimit\\s|\\sorder by\\s)[^()])+|\\(((?:[^()]+|\\((?4)\\))*)\\))*\\s)(order by(?:(?:(?!\\slimit\\s)[^()])+|\\(((?:[^()]+|\\((?6)\\))*)\\))*\\s)?limit\\s+(\\d+)(?:\\s+offset\\s+(\\d+))?#i', $sql, $matches, PREG_SET_ORDER);
     foreach ($matches as $match) {
         if ($this->database->getType() == 'mssql') {
             // This means we have an offset clause
             if (!empty($match[8])) {
                 if ($match[5] === '') {
                     $match[5] = "ORDER BY rand(1) ASC";
                 }
                 $select = $match[1] . ', ROW_NUMBER() OVER (';
                 $select .= $match[5];
                 $select .= ') AS flourish__row__num ';
                 $select .= $match[3];
                 $replacement = 'SELECT * FROM (SELECT ' . trim($match[1]) . ', ROW_NUMBER() OVER (' . $match[5] . ') AS flourish__row__num ' . $match[3] . ') AS original_query WHERE flourish__row__num > ' . $match[8] . ' AND flourish__row__num <= ' . ($match[7] + $match[8]) . ' ORDER BY flourish__row__num';
                 // Otherwise we just have a limit
             } else {
                 $replacement = 'SELECT TOP ' . $match[7] . ' ' . trim($match[1] . $match[3] . $match[5]);
             }
             // While Oracle has the row_number() construct, the rownum pseudo-column is better
         } elseif ($this->database->getType() == 'oracle') {
             // This means we have an offset clause
             if (!empty($match[8])) {
                 $replacement = 'SELECT * FROM (SELECT flourish__sq.*, rownum flourish__row__num FROM (SELECT' . $match[1] . $match[3] . $match[5] . ') flourish__sq WHERE rownum <= ' . ($match[7] + $match[8]) . ') WHERE flourish__row__num > ' . $match[8];
                 // Otherwise we just have a limit
             } else {
                 $replacement = 'SELECT * FROM (SELECT' . $match[1] . $match[3] . $match[5] . ') WHERE rownum <= ' . $match[7];
             }
         } elseif ($this->database->getType() == 'db2') {
             // This means we have an offset clause
             if (!empty($match[8])) {
                 if ($match[5] === '') {
                     $match[5] = "ORDER BY rand(1) ASC";
                 }
                 $select = $match[1] . ', ROW_NUMBER() OVER (';
                 $select .= $match[5];
                 $select .= ') AS flourish__row__num ';
                 $select .= $match[3];
                 $replacement = 'SELECT * FROM (SELECT ' . trim($match[1]) . ', ROW_NUMBER() OVER (' . $match[5] . ') AS flourish__row__num ' . $match[3] . ') AS original_query WHERE flourish__row__num > ' . $match[8] . ' AND flourish__row__num <= ' . ($match[7] + $match[8]) . ' ORDER BY flourish__row__num';
                 // Otherwise we just have a limit
             } else {
                 $replacement = 'SELECT ' . trim($match[1] . $match[3] . $match[5]) . ' FETCH FIRST ' . $match[7] . ' ROWS ONLY';
             }
         }
         $sql = str_replace($match[0], $replacement, $sql);
     }
     return $sql;
 }
Example #21
0
$GLOBALS['ALERTS_TIME_OFFSET'] = 1;
// Allow loading GLOBAL overrides
if (file_exists(TATTLE_ROOT . "/inc/config.override.php")) {
    include_once TATTLE_ROOT . "/inc/config.override.php";
}
//Load in plugin files
$GLOBALS['hooks'] = array();
foreach (glob("plugins/*_plugin.php") as $plugin) {
    include_once $plugin;
}
// Check to make sure the session folder exists
$config_error = '';
$config_exit = false;
if ($GLOBALS['DATABASE_TYPE'] == 'mysql') {
    try {
        $db = new fDatabase('mysql', $GLOBALS['DATABASE_NAME'], $GLOBALS['DATABASE_USER'], $GLOBALS['DATABASE_PASS'], $GLOBALS['DATABASE_HOST'], $GLOBALS['DATABASE_PORT']);
        // Please note that calling this method is not required, and simply
        // causes an exception to be thrown if the connection can not be made
        $db->connect();
    } catch (fAuthorizationException $e) {
        $config_error = "DB error : " . $e->getMessage();
        $config_exit = true;
    } catch (fConnectivityException $e) {
        $config_error = "DB error : " . $e->getMessage();
        $config_exit = true;
    }
} else {
    $config_error = "Unsupported database type : " . $GLOBALS['DATABASE_TYPE'];
    $config_exit = true;
}
if (!$config_exit) {
 /**
  * Adds `WHERE` params to the SQL for the primary keys of this record set
  * 
  * @param  fDatabase $db      The database the query will be executed on 
  * @param  fSchema   $schema  The schema for the database
  * @param  array     $params  The parameters for the fDatabase::query() call
  * @param  string    $route   The route to this table from another table
  * @return array  The params with the `WHERE` clause added
  */
 private function addWhereParams($db, $schema, $params, $route = NULL)
 {
     $table = fORM::tablize($this->class);
     $table_with_route = $route ? $table . '{' . $route . '}' : $table;
     $pk_columns = $schema->getKeys($table, 'primary');
     // We have a multi-field primary key, making things kinda ugly
     if (sizeof($pk_columns) > 1) {
         $escape_pk_columns = array();
         foreach ($pk_columns as $pk_column) {
             $escaped_pk_columns[$pk_column] = $db->escape('%r', $table_with_route . '.' . $pk_column);
         }
         $column_info = $schema->getColumnInfo($table);
         $conditions = array();
         foreach ($this->getPrimaryKeys() as $primary_key) {
             $sub_conditions = array();
             foreach ($pk_columns as $pk_column) {
                 $value = $primary_key[$pk_column];
                 // This makes sure the query performs the way an insert will
                 if ($value === NULL && $column_info[$pk_column]['not_null'] && $column_info[$pk_column]['default'] !== NULL) {
                     $value = $column_info[$pk_column]['default'];
                 }
                 $sub_conditions[] = str_replace('%r', $escaped_pk_columns[$pk_column], fORMDatabase::makeCondition($schema, $table, $pk_column, '=', $value));
                 $params[] = $value;
             }
             $conditions[] = join(' AND ', $sub_conditions);
         }
         $params[0] .= '(' . join(') OR (', $conditions) . ')';
         // We have a single primary key field, making things nice and easy
     } else {
         $first_pk_column = $pk_columns[0];
         $params[0] .= $db->escape('%r IN ', $table_with_route . '.' . $first_pk_column);
         $params[0] .= '(' . $schema->getColumnInfo($table, $first_pk_column, 'placeholder') . ')';
         $params[] = $this->getPrimaryKeys();
     }
     return $params;
 }
Example #23
0
 public function testConnectFailDatabase()
 {
     if (DB_TYPE == 'sqlite') {
         $this->markTestSkipped();
     }
     try {
         $db = new fDatabase(DB_TYPE, 'baddb', DB_USERNAME, DB_PASSWORD, DB_HOST, DB_PORT, 2);
         $db->connect();
     } catch (fNotFoundException $e) {
         $this->assertEquals('Unable to connect to database - database specified not found', $e->getMessage());
     }
     $db->__destruct();
 }
Example #24
0
$GLOBALS['TIMEZONE'] = 'America/New_York';
// Allow loading GLOBAL overrides
if (file_exists(TATTLE_ROOT . "/inc/config.override.php")) {
    include_once TATTLE_ROOT . "/inc/config.override.php";
}
//Load in plugin files
$GLOBALS['hooks'] = array();
foreach (glob("plugins/*_plugin.php") as $plugin) {
    include_once $plugin;
}
// Check to make sure the session folder exists
$config_error = '';
$config_exit = false;
try {
    //Set DB connection (using flourish it isn't actually connected to until the first use)
    $mysql_db = new fDatabase('mysql', $GLOBALS['DATABASE_NAME'], $GLOBALS['DATABASE_USER'], $GLOBALS['DATABASE_PASS'], $GLOBALS['DATABASE_HOST']);
    // Please note that calling this method is not required, and simply
    // causes an exception to be thrown if the connection can not be made
    $mysql_db->connect();
} catch (fAuthorizationException $e) {
    $config_error = "DB error : " . $e->getMessage();
    $config_exit = true;
}
//Connect the db to the ORM functions
fORMDatabase::attach($mysql_db);
$default_plugin_settings = plugin_hook('plugin_settings');
$default_plugin_user_settings = plugin_hook('plugin_user_settings');
$send_methods = plugin_hook('send_methods');
$current_plugin_settings = Setting::findAll(array('type=' => 'system'));
$plugin_settings = $default_plugin_settings;
$plugin_user_settings = $default_plugin_user_settings;
 public function submit()
 {
     try {
         // invitation information
         $email = trim(fRequest::get('email'));
         $stuid = trim(fRequest::get('stuid', 'integer', 0));
         $realname = trim(fRequest::get('realname'));
         // account information
         $username = trim(fRequest::get('username'));
         $password = fRequest::get('password');
         $confirm = fRequest::get('confirm');
         if (empty($email)) {
             throw new fValidationException('请填入Email地址');
         }
         if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
             throw new fValidationException('请填入合法的Email地址');
         }
         if (empty($stuid)) {
             throw new fValidationException('请填入学号');
         }
         if (empty($realname)) {
             throw new fValidationException('请填入真实姓名');
         }
         if (empty($username)) {
             throw new fValidationException('请填入用户名');
         }
         if (empty($password)) {
             throw new fValidationException('请填入密码');
         }
         if (empty($confirm)) {
             throw new fValidationException('请确认密码');
         }
         if ($password != $confirm) {
             throw new fValidationException('两次输入的密码不一致');
         }
         if (strlen($password) < 8) {
             throw new fValidationException('密码太短(至少为8个字符)');
         }
         if (strlen($username) < 3) {
             throw new fValidationException('用户名太短(至少为3个字符)');
         }
         if (strlen($username) > 80) {
             throw new fValidationException('用户名太长(最多80个字符)');
         }
         if (!preg_match('/^[a-z0-9]+$/', $username)) {
             throw new fValidationException('用户名中只允许出现小写字母和数字');
         }
         if (!Name::existid($realname, $stuid)) {
             throw new fValidationException('无效的用户信息(请务必填写用于注册的本科学号,并使用中文姓名注册)');
         }
         $h = acm_userpass_hash($password);
         try {
             $udb = new fDatabase('mysql', UDB_NAME, UDB_USER, UDB_PASS, UDB_HOST);
             $udb->translatedQuery('INSERT INTO users(name,pass,salt,iter,status,email,display_name,created_at,updated_at)' . 'VALUES(%s,%s,%s,%i,2,%s,%s,now(),now())', $username, $h['pass'], $h['salt'], $h['iter'], $email, $realname);
         } catch (fException $e) {
             throw new fValidationException('用户名已存在,或该邮件地址已经注册过');
         }
         //Invitation::markRegistered($email, $invitecode);
         Name::markRegistered($realname, $stuid);
         Activity::fireRegister();
         $this->ajaxReturn(array('result' => 'success'));
     } catch (fException $e) {
         $this->ajaxReturn(array('result' => 'failure', 'message' => $e->getMessage()));
     }
 }
Example #26
0
 /**
  * Finds all of the table names in the SQL and creates the appropriate `FROM` and `GROUP BY` clauses with all necessary joins
  * 
  * The SQL string should contain two placeholders, `:from_clause` and
  * `:group_by_clause`. All columns should be qualified with their full table
  * name. Here is an example SQL string to pass in presumming that the
  * tables users and groups are in a relationship:
  * 
  * {{{
  * SELECT users.* FROM :from_clause WHERE groups.group_id = 5 :group_by_clause ORDER BY lower(users.first_name) ASC
  * }}}
  * 
  * @internal
  * 
  * @param  fDatabase $db      The database the query is to be executed on
  * @param  fSchema   $schema  The schema for the database
  * @param  array     $params  The parameters for the fDatabase::query() call
  * @param  string    $table   The main table to be queried
  * @return array  The params with the SQL `FROM` and `GROUP BY` clauses injected
  */
 public static function injectFromAndGroupByClauses($db, $schema, $params, $table)
 {
     $table = self::cleanTableName($schema, $table);
     $joins = array();
     if (strpos($params[0], ':from_clause') === FALSE) {
         throw new fProgrammerException('No %1$s placeholder was found in:%2$s', ':from_clause', "\n" . $params[0]);
     }
     if (strpos($params[0], ':group_by_clause') === FALSE && !preg_match('#group\\s+by#i', $params[0])) {
         throw new fProgrammerException('No %1$s placeholder was found in:%2$s', ':group_by_clause', "\n" . $params[0]);
     }
     $has_group_by_placeholder = strpos($params[0], ':group_by_clause') !== FALSE ? TRUE : FALSE;
     // Separate the SQL from quoted values
     preg_match_all("#(?:'(?:''|\\\\'|\\\\[^']|[^'\\\\])*')|(?:[^']+)#", $params[0], $matches);
     $table_alias = $table;
     $used_aliases = array();
     $table_map = array();
     // If we are not passing in existing joins, start with the specified table
     if (!$joins) {
         $joins[] = array('join_type' => 'none', 'table_name' => $table, 'table_alias' => $table_alias);
     }
     $used_aliases[] = $table_alias;
     foreach ($matches[0] as $match) {
         if ($match[0] != "'") {
             // This removes quotes from around . in the {route} specified of a shorthand column name
             $match = preg_replace('#(\\{\\w+)"\\."(\\w+\\})#', '\\1.\\2', $match);
             //fCore::expose($match);
             preg_match_all('#(?<!\\w|"|=>)((?:"?((?:\\w+"?\\."?)?\\w+)(?:\\{([\\w.]+)\\})?"?=>)?("?(?:\\w+"?\\."?)?\\w+)(?:\\{([\\w.]+)\\})?"?)\\."?\\w+"?(?=[^\\w".{])#m', $match, $table_matches, PREG_SET_ORDER);
             foreach ($table_matches as $table_match) {
                 if (!isset($table_match[5])) {
                     $table_match[5] = NULL;
                 }
                 if (!empty($table_match[2])) {
                     $table_match[2] = self::cleanTableName($schema, $table_match[2]);
                 }
                 $table_match[4] = self::cleanTableName($schema, $table_match[4]);
                 if (in_array($db->getType(), array('oracle', 'db2'))) {
                     foreach (array(2, 3, 4, 5) as $subpattern) {
                         if (isset($table_match[$subpattern])) {
                             $table_match[$subpattern] = strtolower($table_match[$subpattern]);
                         }
                     }
                 }
                 // This is a related table that is going to join to a once-removed table
                 if (!empty($table_match[2])) {
                     $related_table = $table_match[2];
                     $route = fORMSchema::getRouteName($schema, $table, $related_table, $table_match[3]);
                     $join_name = $table . '_' . $related_table . '{' . $route . '}';
                     $once_removed_table = $table_match[4];
                     // Add the once removed table to the aliases in case we also join directly to it
                     // which may cause the replacements later in this method to convert first to the
                     // real table name and then from the real table to the real table's alias
                     if (!in_array($once_removed_table, $used_aliases)) {
                         $used_aliases[] = $once_removed_table;
                     }
                     self::createJoin($schema, $table, $table_alias, $related_table, $route, $joins, $used_aliases);
                     $route = fORMSchema::getRouteName($schema, $related_table, $once_removed_table, $table_match[5]);
                     $join_name = self::createJoin($schema, $related_table, $joins[$join_name]['table_alias'], $once_removed_table, $route, $joins, $used_aliases);
                     $table_map[$table_match[1]] = $db->escape('%r', $joins[$join_name]['table_alias']);
                     // Remove the once removed table from the aliases so we also join directly to it without an alias
                     unset($used_aliases[array_search($once_removed_table, $used_aliases)]);
                     // This is a related table
                 } elseif (($table_match[4] != $table || fORMSchema::getRoutes($schema, $table, $table_match[4])) && self::cleanTableName($schema, $table_match[1]) != $table) {
                     $related_table = $table_match[4];
                     $route = fORMSchema::getRouteName($schema, $table, $related_table, $table_match[5]);
                     // If the related table is the current table and it is a one-to-many we don't want to join
                     if ($table_match[4] == $table) {
                         $one_to_many_routes = fORMSchema::getRoutes($schema, $table, $related_table, 'one-to-many');
                         if (isset($one_to_many_routes[$route])) {
                             $table_map[$table_match[1]] = $db->escape('%r', $table_alias);
                             continue;
                         }
                     }
                     $join_name = self::createJoin($schema, $table, $table_alias, $related_table, $route, $joins, $used_aliases);
                     $table_map[$table_match[1]] = $db->escape('%r', $joins[$join_name]['table_alias']);
                 }
             }
         }
     }
     // Determine if we joined a *-to-many relationship
     $joined_to_many = FALSE;
     foreach ($joins as $name => $join) {
         if (is_numeric($name)) {
             continue;
         }
         if (substr($name, -5) == '_join') {
             $joined_to_many = TRUE;
             break;
         }
         $main_table = preg_replace('#_' . $join['table_name'] . '{\\w+}$#iD', '', $name);
         $second_table = $join['table_name'];
         $route = preg_replace('#^[^{]+{([\\w.]+)}$#D', '\\1', $name);
         $routes = fORMSchema::getRoutes($schema, $main_table, $second_table, '*-to-many');
         if (isset($routes[$route])) {
             $joined_to_many = TRUE;
             break;
         }
     }
     $found_order_by = FALSE;
     $from_clause = self::createFromClauseFromJoins($db, $joins);
     // If we are joining on a *-to-many relationship we need to group by the
     // columns in the main table to prevent duplicate entries
     if ($joined_to_many) {
         $column_info = $schema->getColumnInfo($table);
         $columns = array();
         foreach ($column_info as $column => $info) {
             $columns[] = $table . '.' . $column;
         }
         $group_by_columns = $db->escape('%r ', $columns);
         $group_by_clause = ' GROUP BY ' . $group_by_columns;
     } else {
         $group_by_clause = ' ';
         $group_by_columns = '';
     }
     // Put the SQL back together
     $new_sql = '';
     $preg_table_pattern = preg_quote($table, '#') . '\\.|' . preg_quote('"' . $table . '"', '#') . '\\.';
     foreach ($matches[0] as $match) {
         $temp_sql = $match;
         // Get rid of the => notation and the :from_clause placeholder
         if ($match[0] !== "'") {
             // This removes quotes from around . in the {route} specified of a shorthand column name
             $temp_sql = preg_replace('#(\\{\\w+)"\\."(\\w+\\})#', '\\1.\\2', $match);
             foreach ($table_map as $arrow_table => $alias) {
                 $temp_sql = preg_replace('#(?<![\\w"])' . preg_quote($arrow_table, '#') . '(?!=[\\w"])#', $alias, $temp_sql);
             }
             // In the ORDER BY clause we need to wrap columns in
             if ($found_order_by && $joined_to_many) {
                 $temp_sql = preg_replace('#(?<!avg\\(|count\\(|max\\(|min\\(|sum\\(|cast\\(|case |when |"|avg\\("|count\\("|max\\("|min\\("|sum\\("|cast\\("|case "|when "|\\{)\\b((?!' . $preg_table_pattern . ')("?\\w+"?\\.)?"?\\w+"?\\."?\\w+"?)(?![^\\w."])#i', 'max(\\1)', $temp_sql);
             }
             if ($joined_to_many && preg_match('#order\\s+by#i', $temp_sql)) {
                 $order_by_found = TRUE;
                 $parts = preg_split('#(order\\s+by)#i', $temp_sql, -1, PREG_SPLIT_DELIM_CAPTURE);
                 $parts[2] = $temp_sql = preg_replace('#(?<!avg\\(|count\\(|max\\(|min\\(|sum\\(|cast\\(|case |when |"|avg\\("|count\\("|max\\("|min\\("|sum\\("|cast\\("|case "|when "|\\{)\\b((?!' . $preg_table_pattern . ')("?\\w+"?\\.)?"?\\w+"?\\."?\\w+"?)(?![^\\w."])#i', 'max(\\1)', $parts[2]);
                 $temp_sql = join('', $parts);
             }
             $temp_sql = str_replace(':from_clause', $from_clause, $temp_sql);
             if ($has_group_by_placeholder) {
                 $temp_sql = preg_replace('#\\s:group_by_clause(\\s|$)#', strtr($group_by_clause, array('\\' => '\\\\', '$' => '\\$')), $temp_sql);
             } elseif ($group_by_columns) {
                 $temp_sql = preg_replace('#(\\sGROUP\\s+BY\\s((?!HAVING|ORDER\\s+BY).)*)\\s#i', '\\1, ' . strtr($group_by_columns, array('\\' => '\\\\', '$' => '\\$')), $temp_sql);
             }
         }
         $new_sql .= $temp_sql;
     }
     $params[0] = $new_sql;
     return $params;
 }
<?php

$page = 'wiki';
require '../header.php';
if (!$user) {
    fURL::redirect('/login.php?forward=/members/wiki.php');
}
?>
<h2>Wiki Account</h2>
<?php 
if ($user->isMember()) {
    $email = $user->getEmail();
    // Make database connection.
    require $_SERVER['DOCUMENT_ROOT'] . '/../var/mediawiki.php';
    $db = new fDatabase($type, $database, $username, $password, $host, $port);
    // Link or unlink a user.
    if ((array_key_exists('link', $_POST) || array_key_exists('unlink', $_POST)) && array_key_exists('wikiuser', $_POST)) {
        fRequest::validateCSRFToken($_POST['token']);
        $user = (int) $_POST['wikiuser'];
        // Check that the MediaWiki and Hackspace e-mails match (and the former is confirmed).
        try {
            $db->translatedQuery('SELECT user_id FROM mwuser WHERE user_id=%i AND user_email=%s AND user_email_authenticated IS NOT NULL', $user, $email)->fetchRow();
            if (array_key_exists('link', $_POST)) {
                // Check that the MediaWiki user is not already a member of the 'sysop' group.
                try {
                    $db->translatedQuery('SELECT ug_user FROM user_groups WHERE ug_user=%i AND ug_group=\'sysop\'', $user)->fetchRow();
                } catch (fNoRowsException $e) {
                    // Add the MediaWiki user to the 'sysop' group.
                    $db->translatedQuery('INSERT INTO user_groups VALUES (%i,\'sysop\')', $user);
                }
            } elseif (array_key_exists('unlink', $_POST)) {