From 6915ac9bc7190df97cbbc2928f0d8535129882d4 Mon Sep 17 00:00:00 2001 From: Sam Minnee Date: Fri, 26 Sep 2008 02:22:51 +0000 Subject: [PATCH] Turned dos line endings into unix git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@63113 467b73ca-7a2a-4603-9d3b-597d59a354a9 --- cli/YearlyTask.php | 18 +- core/model/PDODatabase.php | 1432 +++++++++++++-------------- forms/HasManyComplexTableField.php | 304 +++--- forms/HasOneComplexTableField.php | 146 +-- forms/ManyManyComplexTableField.php | 210 ++-- forms/ToggleField.php | 198 ++-- lang/ru_RU.php | 2 +- parsers/BBCodeParser.php | 232 ++--- parsers/TextParser.php | 104 +- security/MemberLoginForm.php | 414 ++++---- 10 files changed, 1530 insertions(+), 1530 deletions(-) diff --git a/cli/YearlyTask.php b/cli/YearlyTask.php index 6a771e605..d24c74e83 100644 --- a/cli/YearlyTask.php +++ b/cli/YearlyTask.php @@ -1,10 +1,10 @@ - \ No newline at end of file diff --git a/core/model/PDODatabase.php b/core/model/PDODatabase.php index f527b110f..4e1f749f2 100644 --- a/core/model/PDODatabase.php +++ b/core/model/PDODatabase.php @@ -1,716 +1,716 @@ -
  • database: The database to connect with
  • - *
  • server: The server, eg, localhost
  • - *
  • port: The port on which the server is listening (optional)
  • - *
  • instance: Instance of the server, MS SQL only (optional)
  • - *
  • username: The username to log on with
  • - *
  • password: The password to log on with
  • - *
  • database: The database to connect to
  • - */ - public function __construct($parameters) { - $this->param = $parameters; - $connect = self::getConnect($parameters); - $connectWithDB = $connect . ';dbname=' . $parameters['database']; - try { // Try connect to the database, if it does not exist, create it - $this->dbConn = new PDO($connectWithDB, $parameters['username'], $parameters['password']); - } catch (PDOException $e) { - // To do - this is an instance method, not a static method. Call it as such. - if (!self::createDatabase($connect, $parameters['username'], $parameters['password'], $parameters['database'])) { - $this->databaseError("Could not connect to the database, make sure the server is available and user credentials are correct"); - } else { - $this->dbConn = new PDO($connectWithDB, $parameters['username'], $parameters['password']); // After creating the database, connect to it - } - } - parent::__construct(); - } - - /** - * Build the connection string from input. - * @param array $parameters The connection details. - * @return string $connect The connection string. - **/ - public function getConnect($parameters) { - switch ($parameters['type']) { - case "mysql": - $port = '3306'; - $type = 'mysql'; - $instance = ''; - break; - case "postgresql": - $port = '5432'; - $type = 'pgsql'; - $instance = ''; - break; - case "mssql": - $port = '1433'; - if (isset($parameters['instance']) && $parameters['instance'] != '') { - $instance = '\\' . $parameters['instance']; - } else { - $instance = ''; - } - $type = 'mssql'; - break; - default: - $this->databaseError("This database server is not available"); - } - if (isset($parameters['port']) && is_numeric($parameters['port'])) { - $port = $parameters['port']; - } - $connect = $type . ':host=' . $parameters['server'] . $instance . ';port=' . $port; - return $connect; - } - - /** - * Returns true if this database supports collations - */ - public function supportsCollations() { - $collations = false; - switch (self::getDatabaseServer()) { - case "pgsql": // Generally supported in PostgreSQL (supported versions), but handled differently than in MySQL, so do not set - case "mssql": // Generally supported in MS SQL (supported versions), but handled differently than in MySQL, so do not set - $collations = false; - break; - case "mysql": - if (self::getVersion() >= 4.1) { // Supported in MySQL since 4.1 - $collations = true; - } - break; - } - return $collations; - } - - /** - * Get the database version. - * @return float - */ - public function getVersion() { - switch (self::getDatabaseServer()) { - case "mysql": - case "pgsql": - $query = "SELECT VERSION()"; - break; - case "mssql": - $query = "SELECT @@VERSION"; - break; - } - $stmt = $this->dbConn->prepare($query); - $stmt->execute(); - $dbVersion = $stmt->fetchColumn(); - $version = ereg_replace("([A-Za-z-])", "", $dbVersion); - return substr(trim($version), 0, 3); // Just get the major and minor version - } - - /** - * Get the database server, namely mysql, pgsql, or mssql. - * @return string - */ - public function getDatabaseServer() { - return $this->dbConn->getAttribute(PDO::ATTR_DRIVER_NAME); - } - - /** - * Query the database. - * @var string $sql The query to be issued to the database. - * @return result Return the result of the quers (if any). - */ - public function query($sql, $errorLevel = E_USER_ERROR) { - if(isset($_REQUEST['previewwrite']) && in_array(strtolower(substr($sql,0,6)), array('insert','update'))) { - Debug::message("Will execute: $sql"); - return; - } - //Debug::backtrace(); - if(isset($_REQUEST['showqueries'])) { - Debug::message("\n" . $sql . "\n"); - $starttime = microtime(true); - } - - $stmt = $dbConn->prepare($sql); - - $stmt = $this->dbConn->prepare($sql); - $handle = $stmt->execute(); // Execute and save the return value (true or false) - - if(isset($_REQUEST['showqueries'])) { - $duration = microtime(true) - $starttime; - Debug::message("\n" . $duration . "\n"); - } - - if(!$handle && $errorLevel) { - $error = $stmt->errorInfo(); - $this->databaseError("Couldn't run query: $sql | " . $error[2], $errorLevel); - } - return new PDOQuery($this, $stmt); - } - - /** - * Get the ID for the next new record for the table. - * Get the autogenerated ID from the previous INSERT query. - * Simulate mysql_insert_id by fetching the highest ID as there is no other reliable method across databases. - * @return int - */ - public function getGeneratedID($table) { - $stmt = $this->dbConn->prepare("SELECT MAX(ID) FROM $table"); - $handle = $stmt->execute(); - $result = $stmt->fetchColumn(); - return $handle ? $result : 0; - } - - - /** - * OBSOLETE: Get the ID for the next new record for the table. - * @var string $table The name od the table. - * @return int - */ - public function getNextID($table) { - user_error('getNextID is OBSOLETE (and will no longer work properly)', E_USER_WARNING); - $stmt = $this->dbConn->prepare("SELECT MAX(ID)+1 FROM $table"); - $handle = $stmt->execute(); - $result = $stmt->fetchColumn(); - return $handle ? $result : 1; - } - - /** - * Determine if the the table is active. - * @return bool - */ - public function isActive() { - return $this->active ? true : false; - } - - /** - * Create the database and connect to it. This can be called if the - * initial database connection is not successful because the database - * does not exist. - * @param string $connect Connection string - * @param string $username Database username - * @param string $password Database Password - * @param string $database Database to which to create - * @return boolean Returns true if successful - * @todo This shouldn't take any arguments; it should take the information given in the constructor instead. - */ - public function createDatabase() { - try { - $dbh = new PDO($connect, $username, $password); - $stmt = $dbh->prepare("CREATE DATABASE $database"); - $stmt->execute(); - $this->active = true; - } catch (PDOException $e) { - $this->databaseError($e->getMessage()); - return false; - } - return true; - } - - /** - * Returns true if the named database exists. - */ - public function databaseExists($name) { - $SQL_name = Convert::raw2sql($name); - $connect = self::getConnect($this->param); - $connectWithDB = $connect . ';dbname=' . $SQL_name; - try { // Try connect to the database - $testConn = new PDO($connectWithDB, $this->param['username'], $this->param['password']); - } catch (PDOException $e) { - return false; - } - return true; - } - - /** - * Switches to the given database. - * Simply switching database in PDO is not possible, you need to create a new PDO object - */ - public function selectDatabase($dbname) { - $this->dbConn = null; // Remove the old connection - $connect = self::getConnect($param); - $connectWithDB = $connect . ';dbname=' . $dbname; - try { // Try connect to the database, if it does not exist, create it - $this->dbConn = new PDO($connectWithDB, $param['username'], $param['password']); - } catch (PDOException $e) { - if (!self::createDatabase($connect, $param['username'], $param['password'], $dbname)) { - $this->databaseError("Could not connect to the database, make sure the server is available and user credentials are correct"); - } else { - $this->dbConn = new PDO($connectWithDB, $param['username'], $param['password']); // After creating the database, connect to it - } - } - } - - /** - * Create a new table with an integer primary key called ID. - * @var string $tableName The name of the table. - * @return void. - */ - public function createTable($tableName, $fields = null, $indexes = null) { - $fieldSchemas = $indexSchemas = ""; - if ($fields) { - foreach($fields as $k => $v) $fieldSchemas .= "`$k` $v,\n"; - } - - switch (self::getDatabaseServer()) { - case "mysql": - $stmt = $this->dbConn->prepare("CREATE TABLE $tableName (ID INT(11) NOT NULL AUTO_INCREMENT, $fieldSchemas PRIMARY KEY (ID)) TYPE=MyISAM"); - break; - case "pgsql": - $stmt = $this->dbConn->prepare("CREATE TABLE $tableName (ID SERIAL, $fieldSchemas PRIMARY KEY (ID))"); - break; - case "mssql": - $stmt = $this->dbConn->prepare("CREATE TABLE $tableName (ID INT(11) IDENTITY(1,1), $fieldSchemas PRIMARY KEY (ID))"); - break; - default: - $this->databaseError("This database server is not available"); - } - $stmt->execute(); - - if ($indexes) { - self::alterTable($tableName, null, $indexes, null, null); - } - } - - /** - * Alter fields and indexes in existing table. - * @param string $tableName The name of the table. - * @param string $newFields Fields to add. - * @param string $newIndexes Indexes to add. - * @param string $alteredFields Fields to change. - * @param string $alteredIndexes Indexes to change. - * @return void. - */ - public function alterTable($table, $newFields = null, $newIndexes = null, $alteredFields = null, $alteredIndexes = null) { - - if ($newFields) { - foreach ($newFields as $field => $type) { - $stmt = $this->dbConn->prepare("ALTER TABLE $table ADD $field $type"); - $stmt->execute(); - } - } - - if ($newIndexes) { - foreach ($newIndexes as $name => $column) { - $stmt = $this->dbConn->prepare("CREATE INDEX $name ON $table $column"); - $stmt->execute(); - } - } - - if ($alteredFields) { - foreach ($alteredFields as $field => $type) { - self::alterField($table, $field, $type); - } - } - - if ($alteredIndexes) { - foreach ($newIndexes as $name => $column) { - $this->dbConn->query("DROP INDEX $name"); - $stmt = $this->dbConn->prepare("CREATE INDEX $name ON $table $column"); - $stmt->execute(); - } - } - } - - /** - * Rename an existing table, the TO is necessary for PostgreSQL and MS SQL. - * @param string $oldTableName The name of the existing table. - * @param string $newTableName How the table should be named from now on. - * @return void. - */ - public function renameTable($oldTableName, $newTableName) { - $stmt = $this->dbConn->prepare("ALTER TABLE $oldTableName RENAME TO $newTableName"); - $stmt->execute(); - } - - /** - * Checks a table's integrity and repairs it if necessary - only available in MySQL, not supported in PostgreSQL and MS SQL. - * @var string $tableName The name of the table. - * @return boolean Return true if the table has integrity after the method is complete. - */ - public function checkAndRepairTable($tableName) { - if ($parameters['type'] == "mysql") { - if (!$this->runTableCheckCommand("CHECK TABLE `$tableName`")) { - if(!Database::$supressOutput) { - echo "
  • Table $tableName: repaired
  • "; - } - return $this->runTableCheckCommand("REPAIR TABLE `$tableName` USE_FRM"); - } else { - return true; - } - } else { - $this->databaseError("Checking and repairing of tables is only supported in MySQL, for other databases please do manual checks"); - return false; - } - } - - /** - * Helper function used by checkAndRepairTable. - * @param string $sql Query to run. - * @return boolean Returns if the query returns a successful result. - */ - protected function runTableCheckCommand($sql) { - foreach($this->dbConn->query($sql) as $testRecord) { - if(strtolower($testRecord['Msg_text']) != 'ok') { - return false; - } - } - return true; - } - - /** - * Add the given field to the given table. - * @param string $tableName The name of the table on which to create the field. - * @param string $fieldName The field to create. - * @param string $fieldSpec The datatype of the field. - * @return void - */ - public function createField($tableName, $fieldName, $fieldSpec) { - $stmt = $this->dbConn->prepare("ALTER TABLE $tableName ADD $fieldName $fieldSpec"); - $stmt->execute(); - } - - /** - * Change the database type of the given field. - * @param string $table The table where to change the field. - * @param string $field The field to change. - * @param string $type The new type of the field - * @return void - */ - public function alterField($table, $field, $type) { - switch (self::getDatabaseServer()) { - case "mysql": - $stmt = $this->dbConn->prepare("ALTER TABLE $table CHANGE $field $field $type"); - break; - case "pgsql": - $stmt = $this->dbConn->prepare(" - BEGIN; - ALTER TABLE $table RENAME $field TO oldfield; - ALTER TABLE $table ADD COLUMN $field $type; - UPDATE $table SET $field = CAST(oldfield AS $type); - ALTER TABLE $table DROP COLUMN oldfield; - COMMIT; - "); - break; - case "mssql": - $stmt = $this->dbConn->prepare("ALTER TABLE $table ALTER COLUMN $field $type"); - break; - default: - $this->databaseError("This database server is not available"); - } - $stmt->execute(); - } - - /** - * Create an index on a table. - * @param string $tableName The name of the table. - * @param string $indexName The name of the index. - * @param string $indexSpec The specification of the index, see Database::requireIndex() for more details. - * @return void - */ - public function createIndex($tableName, $indexName, $indexSpec) { - $stmt = $this->dbConn->prepare("CREATE INDEX $indexName ON $tableName $indexSpec"); - $stmt->execute(); - } - - /** - * Alter an index on a table. - * @param string $tableName The name of the table. - * @param string $indexName The name of the index. - * @param string $indexSpec The specification of the index, see Database::requireIndex() for more details. - * @return void - */ - public function alterIndex($tableName, $indexName, $indexSpec) { - $this->dbConn->query("DROP INDEX $indexName"); - $stmt = $this->dbConn->prepare("CREATE INDEX $indexName ON $tableName $indexSpec"); - $stmt->execute(); - } - - /** - * Get a list of all the fields for the given table. - * The results are not totally equal for all databases (for example collations are handled very differently, PostgreSQL disregards zerofill,...) - * but as close as possible and necessary. - * @param string $able Table of which to show the fields. - * Returns a map of field name => field spec. - */ - public function fieldList($table) { - switch (self::getDatabaseServer()) { - case "mysql": - foreach ($this->dbConn->query("SHOW FULL FIELDS IN $table") as $field) { - $fieldSpec = $field['Type']; - if(!$field['Null'] || $field['Null'] == 'NO') { - $fieldSpec .= ' not null'; - } - if($field['Collation'] && $field['Collation'] != 'NULL') { - $values = $this->dbConn->prepare("SHOW COLLATION LIKE '$field[Collation]'"); - $values->execute(); - $collInfo = $values->fetchColumn(); - $fieldSpec .= " character set $collInfo[Charset] collate $field[Collation]"; - } - if($field['Default'] || $field['Default'] === "0") { - $fieldSpec .= " default '" . addslashes($field['Default']) . "'"; - } - if($field['Extra']) $fieldSpec .= " $field[Extra]"; - $fieldList[$field['Field']] = $fieldSpec; - } - break; - case "pgsql": - foreach ($this->dbConn->query(" - SELECT - column_name AS cname, - column_default AS cdefault, - is_nullable AS nullable, - data_type AS dtype, - character_maximum_length AS maxlength - FROM - information_schema.columns - WHERE - table_name = $table - ") as $field) { - if ($field['maxlength']) { - $fieldSpec = $field['dtype'] . "(" . $field['maxlength'] . ")"; - } else { - $fieldSpec = $field['dtype']; - } - if ($field['nullable'] == 'NO') { - $fieldSpec .= ' not null'; - } - if($field['cdefault'] || $field['cdefault'] === "0") { - $fieldSpec .= " default '" . addslashes($field['cdefault']) . "'"; - } - $fieldList[$field['cname']] = $fieldSpec; - } - break; - case "mssql": - foreach ($this->dbConn->query(" - SELECT - COLUMN_NAME AS 'cname', - COLUMN_DEFAULT AS 'cdefault', - IS_NULLABLE AS 'nullable', - DATA_TYPE AS 'dtype', - COLLATION_NAME AS 'collname', - CHARACTER_SET_NAME AS 'cset', - CHARACTER_MAXIMUM_LENGTH AS 'maxlength' - FROM - information_schema.columns - WHERE - TABLE_NAME = '$table' - ") as $field) { - if ($field['maxlength']) { - $fieldSpec = $field['dtype'] . "(" . $field['maxlength'] . ")"; - } else { - $fieldSpec = $field['dtype']; - } - if ($field['nullable'] == 'NO') { - $fieldSpec .= ' not null'; - } - - if($field['collname'] && $field['collname'] != 'NULL') { - $fieldSpec .= " character set $field[cset] collate $field[collname]"; - } - - if($field['cdefault'] || $field['cdefault'] === "0") { - $fieldSpec .= " default '" . addslashes($field['cdefault']) . "'"; - } - - $fieldList[$field['cname']] = $fieldSpec; - } - break; - default: - $this->databaseError("This database server is not available"); - } - - return $fieldList; - } - - /** - * Get a list of all the indexes for the given table. - * @param string $able Table of which to show the indexes. - * Returns a map of indexes. - */ - public function indexList($table) { - switch (self::getDatabaseServer()) { - case "mysql": - foreach($this->dbConn->query("SHOW INDEXES IN '$table'") as $index) { - $groupedIndexes[$index['Key_name']]['fields'][$index['Seq_in_index']] = $index['Column_name']; - if($index['Index_type'] == 'FULLTEXT') { - $groupedIndexes[$index['Key_name']]['type'] = 'fulltext '; - } else if(!$index['Non_unique']) { - $groupedIndexes[$index['Key_name']]['type'] = 'unique '; - } else { - $groupedIndexes[$index['Key_name']]['type'] = ''; - } - } - foreach($groupedIndexes as $index => $details) { - ksort($details['fields']); - $indexList[$index] = $details['type'] . '(' . implode(',',$details['fields']) . ')'; - } - break; - case "pgsql": - foreach($this->dbConn->query("SELECT indexname, indexdef FROM pg_indexes WHERE tablename = '$table'") as $index) { - $indexList[$index['indexname']] = $index['indexdef']; - } - break; - case "mssql": - foreach($this->dbConn->query(" - SELECT - i.name AS 'iname', - i.type_desc AS 'itype', - s.name AS 'sname' - FROM - sys.indexes i, - sys.objects o, - sys.index_columns c, - sys.columns s - WHERE - o.name = '$table' - AND o.object_id = i.object_id - AND o.object_id = c.object_id - AND o.object_id = s.object_id - AND s.column_id = c.column_id - ") as $index) { - $indexList[$index['iname']] = $index['itype'] . " (" . $index['sname'] . ")"; - } - break; - default: - $this->databaseError("This database server is not available"); - } - - return $indexList; - } - - /** - * Returns a list of all the tables in the database. - * Table names will all be in lowercase. - * Returns a map of a table. - */ - public function tableList() { - switch (self::getDatabaseServer()) { - case "mysql": - $sql = "SHOW TABLES"; - break; - case "pgsql": - $sql = "SELECT tablename FROM pg_tables WHERE tablename NOT ILIKE 'pg_%' AND tablename NOT ILIKE 'sql_%'"; - break; - case "mssql": - $sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME NOT LIKE 'sysdiagrams%'"; - break; - default: - $this->databaseError("This database server is not available"); - } - if (is_array($this->dbConn->query($sql))) { - foreach($this->dbConn->query($sql) as $record) { - $table = strtolower(reset($record)); - $tables[$table] = $table; - } - } - return isset($tables) ? $tables : null; - } - - /** - * Return the number of rows affected (DELETE, INSERT, or UPDATE) by the previous operation. - */ - public function affectedRows() { - return $stmt->rowCount(); - } -} - -/** - * A result-set from a database query (array). - * @package sapphire - * @subpackage model - */ -class PDOQuery extends Query { - private $database; - private $handle; - - /** - * The object that holds the result set. - * @var $stmt - */ - private $stmt; - - /** - * Hook the result-set given into a Query class, suitable for use by sapphire. - * @param PDO object $stmt The object of all returned values. - */ - public function __construct(PDODatabase $database, $stmt) { - $this->database = $database; - $this->stmt = $stmt; - parent::__construct(); - } - - - /** - * Free the result-set given into a Query class. - */ - public function __destroy() { - $this->stmt = null; - } - - - /** - * Determine if a given element is part of the result set. - * @param string string $row The element to search for. - */ - public function seek($row) { - return in_array($row, $this->stmt->fetchAll()); - } - - /** - * Return the number of results. - */ - public function numRecords() { - $value = $this->stmt->fetchAll(); - return count($value); - } - - - /** - * - */ - public function nextRecord() { - $record = $this->stmt->fetch(PDO::FETCH_ASSOC); - if (count($record)) { - return $record; - } else { - return false; - } - } -} - - -?> +
  • database: The database to connect with
  • + *
  • server: The server, eg, localhost
  • + *
  • port: The port on which the server is listening (optional)
  • + *
  • instance: Instance of the server, MS SQL only (optional)
  • + *
  • username: The username to log on with
  • + *
  • password: The password to log on with
  • + *
  • database: The database to connect to
  • + */ + public function __construct($parameters) { + $this->param = $parameters; + $connect = self::getConnect($parameters); + $connectWithDB = $connect . ';dbname=' . $parameters['database']; + try { // Try connect to the database, if it does not exist, create it + $this->dbConn = new PDO($connectWithDB, $parameters['username'], $parameters['password']); + } catch (PDOException $e) { + // To do - this is an instance method, not a static method. Call it as such. + if (!self::createDatabase($connect, $parameters['username'], $parameters['password'], $parameters['database'])) { + $this->databaseError("Could not connect to the database, make sure the server is available and user credentials are correct"); + } else { + $this->dbConn = new PDO($connectWithDB, $parameters['username'], $parameters['password']); // After creating the database, connect to it + } + } + parent::__construct(); + } + + /** + * Build the connection string from input. + * @param array $parameters The connection details. + * @return string $connect The connection string. + **/ + public function getConnect($parameters) { + switch ($parameters['type']) { + case "mysql": + $port = '3306'; + $type = 'mysql'; + $instance = ''; + break; + case "postgresql": + $port = '5432'; + $type = 'pgsql'; + $instance = ''; + break; + case "mssql": + $port = '1433'; + if (isset($parameters['instance']) && $parameters['instance'] != '') { + $instance = '\\' . $parameters['instance']; + } else { + $instance = ''; + } + $type = 'mssql'; + break; + default: + $this->databaseError("This database server is not available"); + } + if (isset($parameters['port']) && is_numeric($parameters['port'])) { + $port = $parameters['port']; + } + $connect = $type . ':host=' . $parameters['server'] . $instance . ';port=' . $port; + return $connect; + } + + /** + * Returns true if this database supports collations + */ + public function supportsCollations() { + $collations = false; + switch (self::getDatabaseServer()) { + case "pgsql": // Generally supported in PostgreSQL (supported versions), but handled differently than in MySQL, so do not set + case "mssql": // Generally supported in MS SQL (supported versions), but handled differently than in MySQL, so do not set + $collations = false; + break; + case "mysql": + if (self::getVersion() >= 4.1) { // Supported in MySQL since 4.1 + $collations = true; + } + break; + } + return $collations; + } + + /** + * Get the database version. + * @return float + */ + public function getVersion() { + switch (self::getDatabaseServer()) { + case "mysql": + case "pgsql": + $query = "SELECT VERSION()"; + break; + case "mssql": + $query = "SELECT @@VERSION"; + break; + } + $stmt = $this->dbConn->prepare($query); + $stmt->execute(); + $dbVersion = $stmt->fetchColumn(); + $version = ereg_replace("([A-Za-z-])", "", $dbVersion); + return substr(trim($version), 0, 3); // Just get the major and minor version + } + + /** + * Get the database server, namely mysql, pgsql, or mssql. + * @return string + */ + public function getDatabaseServer() { + return $this->dbConn->getAttribute(PDO::ATTR_DRIVER_NAME); + } + + /** + * Query the database. + * @var string $sql The query to be issued to the database. + * @return result Return the result of the quers (if any). + */ + public function query($sql, $errorLevel = E_USER_ERROR) { + if(isset($_REQUEST['previewwrite']) && in_array(strtolower(substr($sql,0,6)), array('insert','update'))) { + Debug::message("Will execute: $sql"); + return; + } + //Debug::backtrace(); + if(isset($_REQUEST['showqueries'])) { + Debug::message("\n" . $sql . "\n"); + $starttime = microtime(true); + } + + $stmt = $dbConn->prepare($sql); + + $stmt = $this->dbConn->prepare($sql); + $handle = $stmt->execute(); // Execute and save the return value (true or false) + + if(isset($_REQUEST['showqueries'])) { + $duration = microtime(true) - $starttime; + Debug::message("\n" . $duration . "\n"); + } + + if(!$handle && $errorLevel) { + $error = $stmt->errorInfo(); + $this->databaseError("Couldn't run query: $sql | " . $error[2], $errorLevel); + } + return new PDOQuery($this, $stmt); + } + + /** + * Get the ID for the next new record for the table. + * Get the autogenerated ID from the previous INSERT query. + * Simulate mysql_insert_id by fetching the highest ID as there is no other reliable method across databases. + * @return int + */ + public function getGeneratedID($table) { + $stmt = $this->dbConn->prepare("SELECT MAX(ID) FROM $table"); + $handle = $stmt->execute(); + $result = $stmt->fetchColumn(); + return $handle ? $result : 0; + } + + + /** + * OBSOLETE: Get the ID for the next new record for the table. + * @var string $table The name od the table. + * @return int + */ + public function getNextID($table) { + user_error('getNextID is OBSOLETE (and will no longer work properly)', E_USER_WARNING); + $stmt = $this->dbConn->prepare("SELECT MAX(ID)+1 FROM $table"); + $handle = $stmt->execute(); + $result = $stmt->fetchColumn(); + return $handle ? $result : 1; + } + + /** + * Determine if the the table is active. + * @return bool + */ + public function isActive() { + return $this->active ? true : false; + } + + /** + * Create the database and connect to it. This can be called if the + * initial database connection is not successful because the database + * does not exist. + * @param string $connect Connection string + * @param string $username Database username + * @param string $password Database Password + * @param string $database Database to which to create + * @return boolean Returns true if successful + * @todo This shouldn't take any arguments; it should take the information given in the constructor instead. + */ + public function createDatabase() { + try { + $dbh = new PDO($connect, $username, $password); + $stmt = $dbh->prepare("CREATE DATABASE $database"); + $stmt->execute(); + $this->active = true; + } catch (PDOException $e) { + $this->databaseError($e->getMessage()); + return false; + } + return true; + } + + /** + * Returns true if the named database exists. + */ + public function databaseExists($name) { + $SQL_name = Convert::raw2sql($name); + $connect = self::getConnect($this->param); + $connectWithDB = $connect . ';dbname=' . $SQL_name; + try { // Try connect to the database + $testConn = new PDO($connectWithDB, $this->param['username'], $this->param['password']); + } catch (PDOException $e) { + return false; + } + return true; + } + + /** + * Switches to the given database. + * Simply switching database in PDO is not possible, you need to create a new PDO object + */ + public function selectDatabase($dbname) { + $this->dbConn = null; // Remove the old connection + $connect = self::getConnect($param); + $connectWithDB = $connect . ';dbname=' . $dbname; + try { // Try connect to the database, if it does not exist, create it + $this->dbConn = new PDO($connectWithDB, $param['username'], $param['password']); + } catch (PDOException $e) { + if (!self::createDatabase($connect, $param['username'], $param['password'], $dbname)) { + $this->databaseError("Could not connect to the database, make sure the server is available and user credentials are correct"); + } else { + $this->dbConn = new PDO($connectWithDB, $param['username'], $param['password']); // After creating the database, connect to it + } + } + } + + /** + * Create a new table with an integer primary key called ID. + * @var string $tableName The name of the table. + * @return void. + */ + public function createTable($tableName, $fields = null, $indexes = null) { + $fieldSchemas = $indexSchemas = ""; + if ($fields) { + foreach($fields as $k => $v) $fieldSchemas .= "`$k` $v,\n"; + } + + switch (self::getDatabaseServer()) { + case "mysql": + $stmt = $this->dbConn->prepare("CREATE TABLE $tableName (ID INT(11) NOT NULL AUTO_INCREMENT, $fieldSchemas PRIMARY KEY (ID)) TYPE=MyISAM"); + break; + case "pgsql": + $stmt = $this->dbConn->prepare("CREATE TABLE $tableName (ID SERIAL, $fieldSchemas PRIMARY KEY (ID))"); + break; + case "mssql": + $stmt = $this->dbConn->prepare("CREATE TABLE $tableName (ID INT(11) IDENTITY(1,1), $fieldSchemas PRIMARY KEY (ID))"); + break; + default: + $this->databaseError("This database server is not available"); + } + $stmt->execute(); + + if ($indexes) { + self::alterTable($tableName, null, $indexes, null, null); + } + } + + /** + * Alter fields and indexes in existing table. + * @param string $tableName The name of the table. + * @param string $newFields Fields to add. + * @param string $newIndexes Indexes to add. + * @param string $alteredFields Fields to change. + * @param string $alteredIndexes Indexes to change. + * @return void. + */ + public function alterTable($table, $newFields = null, $newIndexes = null, $alteredFields = null, $alteredIndexes = null) { + + if ($newFields) { + foreach ($newFields as $field => $type) { + $stmt = $this->dbConn->prepare("ALTER TABLE $table ADD $field $type"); + $stmt->execute(); + } + } + + if ($newIndexes) { + foreach ($newIndexes as $name => $column) { + $stmt = $this->dbConn->prepare("CREATE INDEX $name ON $table $column"); + $stmt->execute(); + } + } + + if ($alteredFields) { + foreach ($alteredFields as $field => $type) { + self::alterField($table, $field, $type); + } + } + + if ($alteredIndexes) { + foreach ($newIndexes as $name => $column) { + $this->dbConn->query("DROP INDEX $name"); + $stmt = $this->dbConn->prepare("CREATE INDEX $name ON $table $column"); + $stmt->execute(); + } + } + } + + /** + * Rename an existing table, the TO is necessary for PostgreSQL and MS SQL. + * @param string $oldTableName The name of the existing table. + * @param string $newTableName How the table should be named from now on. + * @return void. + */ + public function renameTable($oldTableName, $newTableName) { + $stmt = $this->dbConn->prepare("ALTER TABLE $oldTableName RENAME TO $newTableName"); + $stmt->execute(); + } + + /** + * Checks a table's integrity and repairs it if necessary - only available in MySQL, not supported in PostgreSQL and MS SQL. + * @var string $tableName The name of the table. + * @return boolean Return true if the table has integrity after the method is complete. + */ + public function checkAndRepairTable($tableName) { + if ($parameters['type'] == "mysql") { + if (!$this->runTableCheckCommand("CHECK TABLE `$tableName`")) { + if(!Database::$supressOutput) { + echo "
  • Table $tableName: repaired
  • "; + } + return $this->runTableCheckCommand("REPAIR TABLE `$tableName` USE_FRM"); + } else { + return true; + } + } else { + $this->databaseError("Checking and repairing of tables is only supported in MySQL, for other databases please do manual checks"); + return false; + } + } + + /** + * Helper function used by checkAndRepairTable. + * @param string $sql Query to run. + * @return boolean Returns if the query returns a successful result. + */ + protected function runTableCheckCommand($sql) { + foreach($this->dbConn->query($sql) as $testRecord) { + if(strtolower($testRecord['Msg_text']) != 'ok') { + return false; + } + } + return true; + } + + /** + * Add the given field to the given table. + * @param string $tableName The name of the table on which to create the field. + * @param string $fieldName The field to create. + * @param string $fieldSpec The datatype of the field. + * @return void + */ + public function createField($tableName, $fieldName, $fieldSpec) { + $stmt = $this->dbConn->prepare("ALTER TABLE $tableName ADD $fieldName $fieldSpec"); + $stmt->execute(); + } + + /** + * Change the database type of the given field. + * @param string $table The table where to change the field. + * @param string $field The field to change. + * @param string $type The new type of the field + * @return void + */ + public function alterField($table, $field, $type) { + switch (self::getDatabaseServer()) { + case "mysql": + $stmt = $this->dbConn->prepare("ALTER TABLE $table CHANGE $field $field $type"); + break; + case "pgsql": + $stmt = $this->dbConn->prepare(" + BEGIN; + ALTER TABLE $table RENAME $field TO oldfield; + ALTER TABLE $table ADD COLUMN $field $type; + UPDATE $table SET $field = CAST(oldfield AS $type); + ALTER TABLE $table DROP COLUMN oldfield; + COMMIT; + "); + break; + case "mssql": + $stmt = $this->dbConn->prepare("ALTER TABLE $table ALTER COLUMN $field $type"); + break; + default: + $this->databaseError("This database server is not available"); + } + $stmt->execute(); + } + + /** + * Create an index on a table. + * @param string $tableName The name of the table. + * @param string $indexName The name of the index. + * @param string $indexSpec The specification of the index, see Database::requireIndex() for more details. + * @return void + */ + public function createIndex($tableName, $indexName, $indexSpec) { + $stmt = $this->dbConn->prepare("CREATE INDEX $indexName ON $tableName $indexSpec"); + $stmt->execute(); + } + + /** + * Alter an index on a table. + * @param string $tableName The name of the table. + * @param string $indexName The name of the index. + * @param string $indexSpec The specification of the index, see Database::requireIndex() for more details. + * @return void + */ + public function alterIndex($tableName, $indexName, $indexSpec) { + $this->dbConn->query("DROP INDEX $indexName"); + $stmt = $this->dbConn->prepare("CREATE INDEX $indexName ON $tableName $indexSpec"); + $stmt->execute(); + } + + /** + * Get a list of all the fields for the given table. + * The results are not totally equal for all databases (for example collations are handled very differently, PostgreSQL disregards zerofill,...) + * but as close as possible and necessary. + * @param string $able Table of which to show the fields. + * Returns a map of field name => field spec. + */ + public function fieldList($table) { + switch (self::getDatabaseServer()) { + case "mysql": + foreach ($this->dbConn->query("SHOW FULL FIELDS IN $table") as $field) { + $fieldSpec = $field['Type']; + if(!$field['Null'] || $field['Null'] == 'NO') { + $fieldSpec .= ' not null'; + } + if($field['Collation'] && $field['Collation'] != 'NULL') { + $values = $this->dbConn->prepare("SHOW COLLATION LIKE '$field[Collation]'"); + $values->execute(); + $collInfo = $values->fetchColumn(); + $fieldSpec .= " character set $collInfo[Charset] collate $field[Collation]"; + } + if($field['Default'] || $field['Default'] === "0") { + $fieldSpec .= " default '" . addslashes($field['Default']) . "'"; + } + if($field['Extra']) $fieldSpec .= " $field[Extra]"; + $fieldList[$field['Field']] = $fieldSpec; + } + break; + case "pgsql": + foreach ($this->dbConn->query(" + SELECT + column_name AS cname, + column_default AS cdefault, + is_nullable AS nullable, + data_type AS dtype, + character_maximum_length AS maxlength + FROM + information_schema.columns + WHERE + table_name = $table + ") as $field) { + if ($field['maxlength']) { + $fieldSpec = $field['dtype'] . "(" . $field['maxlength'] . ")"; + } else { + $fieldSpec = $field['dtype']; + } + if ($field['nullable'] == 'NO') { + $fieldSpec .= ' not null'; + } + if($field['cdefault'] || $field['cdefault'] === "0") { + $fieldSpec .= " default '" . addslashes($field['cdefault']) . "'"; + } + $fieldList[$field['cname']] = $fieldSpec; + } + break; + case "mssql": + foreach ($this->dbConn->query(" + SELECT + COLUMN_NAME AS 'cname', + COLUMN_DEFAULT AS 'cdefault', + IS_NULLABLE AS 'nullable', + DATA_TYPE AS 'dtype', + COLLATION_NAME AS 'collname', + CHARACTER_SET_NAME AS 'cset', + CHARACTER_MAXIMUM_LENGTH AS 'maxlength' + FROM + information_schema.columns + WHERE + TABLE_NAME = '$table' + ") as $field) { + if ($field['maxlength']) { + $fieldSpec = $field['dtype'] . "(" . $field['maxlength'] . ")"; + } else { + $fieldSpec = $field['dtype']; + } + if ($field['nullable'] == 'NO') { + $fieldSpec .= ' not null'; + } + + if($field['collname'] && $field['collname'] != 'NULL') { + $fieldSpec .= " character set $field[cset] collate $field[collname]"; + } + + if($field['cdefault'] || $field['cdefault'] === "0") { + $fieldSpec .= " default '" . addslashes($field['cdefault']) . "'"; + } + + $fieldList[$field['cname']] = $fieldSpec; + } + break; + default: + $this->databaseError("This database server is not available"); + } + + return $fieldList; + } + + /** + * Get a list of all the indexes for the given table. + * @param string $able Table of which to show the indexes. + * Returns a map of indexes. + */ + public function indexList($table) { + switch (self::getDatabaseServer()) { + case "mysql": + foreach($this->dbConn->query("SHOW INDEXES IN '$table'") as $index) { + $groupedIndexes[$index['Key_name']]['fields'][$index['Seq_in_index']] = $index['Column_name']; + if($index['Index_type'] == 'FULLTEXT') { + $groupedIndexes[$index['Key_name']]['type'] = 'fulltext '; + } else if(!$index['Non_unique']) { + $groupedIndexes[$index['Key_name']]['type'] = 'unique '; + } else { + $groupedIndexes[$index['Key_name']]['type'] = ''; + } + } + foreach($groupedIndexes as $index => $details) { + ksort($details['fields']); + $indexList[$index] = $details['type'] . '(' . implode(',',$details['fields']) . ')'; + } + break; + case "pgsql": + foreach($this->dbConn->query("SELECT indexname, indexdef FROM pg_indexes WHERE tablename = '$table'") as $index) { + $indexList[$index['indexname']] = $index['indexdef']; + } + break; + case "mssql": + foreach($this->dbConn->query(" + SELECT + i.name AS 'iname', + i.type_desc AS 'itype', + s.name AS 'sname' + FROM + sys.indexes i, + sys.objects o, + sys.index_columns c, + sys.columns s + WHERE + o.name = '$table' + AND o.object_id = i.object_id + AND o.object_id = c.object_id + AND o.object_id = s.object_id + AND s.column_id = c.column_id + ") as $index) { + $indexList[$index['iname']] = $index['itype'] . " (" . $index['sname'] . ")"; + } + break; + default: + $this->databaseError("This database server is not available"); + } + + return $indexList; + } + + /** + * Returns a list of all the tables in the database. + * Table names will all be in lowercase. + * Returns a map of a table. + */ + public function tableList() { + switch (self::getDatabaseServer()) { + case "mysql": + $sql = "SHOW TABLES"; + break; + case "pgsql": + $sql = "SELECT tablename FROM pg_tables WHERE tablename NOT ILIKE 'pg_%' AND tablename NOT ILIKE 'sql_%'"; + break; + case "mssql": + $sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND TABLE_NAME NOT LIKE 'sysdiagrams%'"; + break; + default: + $this->databaseError("This database server is not available"); + } + if (is_array($this->dbConn->query($sql))) { + foreach($this->dbConn->query($sql) as $record) { + $table = strtolower(reset($record)); + $tables[$table] = $table; + } + } + return isset($tables) ? $tables : null; + } + + /** + * Return the number of rows affected (DELETE, INSERT, or UPDATE) by the previous operation. + */ + public function affectedRows() { + return $stmt->rowCount(); + } +} + +/** + * A result-set from a database query (array). + * @package sapphire + * @subpackage model + */ +class PDOQuery extends Query { + private $database; + private $handle; + + /** + * The object that holds the result set. + * @var $stmt + */ + private $stmt; + + /** + * Hook the result-set given into a Query class, suitable for use by sapphire. + * @param PDO object $stmt The object of all returned values. + */ + public function __construct(PDODatabase $database, $stmt) { + $this->database = $database; + $this->stmt = $stmt; + parent::__construct(); + } + + + /** + * Free the result-set given into a Query class. + */ + public function __destroy() { + $this->stmt = null; + } + + + /** + * Determine if a given element is part of the result set. + * @param string string $row The element to search for. + */ + public function seek($row) { + return in_array($row, $this->stmt->fetchAll()); + } + + /** + * Return the number of results. + */ + public function numRecords() { + $value = $this->stmt->fetchAll(); + return count($value); + } + + + /** + * + */ + public function nextRecord() { + $record = $this->stmt->fetch(PDO::FETCH_ASSOC); + if (count($record)) { + return $record; + } else { + return false; + } + } +} + + +?> diff --git a/forms/HasManyComplexTableField.php b/forms/HasManyComplexTableField.php index 9bdf462c5..10927eb7e 100644 --- a/forms/HasManyComplexTableField.php +++ b/forms/HasManyComplexTableField.php @@ -1,153 +1,153 @@ -Markable = true; - - $this->joinField = $this->getParentIdName($this->controller->ClassName, $this->sourceClass); - } - - function getQuery($limitClause = null) { - if($this->customQuery) { - $query = $this->customQuery; - $query->select[] = "{$this->sourceClass}.ID AS ID"; - $query->select[] = "{$this->sourceClass}.ClassName AS ClassName"; - $query->select[] = "{$this->sourceClass}.ClassName AS RecordClassName"; - } - else { - $query = singleton($this->sourceClass)->extendedSQL($this->sourceFilter, $this->sourceSort, $limitClause, $this->sourceJoin); - - // Add more selected fields if they are from joined table. - - $SNG = singleton($this->sourceClass); - foreach($this->FieldList() as $k => $title) { - if(! $SNG->hasField($k) && ! $SNG->hasMethod('get' . $k)) - $query->select[] = $k; - } - } - return clone $query; - } - - function sourceItems() { - if($this->sourceItems) - return $this->sourceItems; - - $limitClause = ''; - if(isset($_REQUEST[ 'ctf' ][ $this->Name() ][ 'start' ]) && is_numeric($_REQUEST[ 'ctf' ][ $this->Name() ][ 'start' ])) - $limitClause = $_REQUEST[ 'ctf' ][ $this->Name() ][ 'start' ] . ", $this->pageSize"; - else - $limitClause = "0, $this->pageSize"; - - $dataQuery = $this->getQuery($limitClause); - $records = $dataQuery->execute(); - $items = new DataObjectSet(); - foreach($records as $record) { - if(! get_class($record)) - $record = new DataObject($record); - $items->push($record); - } - - $dataQuery = $this->getQuery(); - $records = $dataQuery->execute(); - $unpagedItems = new DataObjectSet(); - foreach($records as $record) { - if(! get_class($record)) - $record = new DataObject($record); - $unpagedItems->push($record); - } - $this->unpagedSourceItems = $unpagedItems; - - $this->totalCount = ($this->unpagedSourceItems) ? $this->unpagedSourceItems->TotalItems() : null; - - return $items; - } - - function getControllerID() { - return $this->controller->ID; - } - - function saveInto(DataObject $record) { - $fieldName = $this->name; - $saveDest = $record->$fieldName(); - - if(! $saveDest) - user_error("HasManyComplexTableField::saveInto() Field '$fieldName' not found on $record->class.$record->ID", E_USER_ERROR); - - $items = array(); - - if($list = $this->value[ $this->htmlListField ]) { - if($list != 'undefined') - $items = explode(',', $list); - } - - $saveDest->setByIDList($items); - } - - function setAddTitle($addTitle) { - if(is_string($addTitle)) - $this->addTitle = $addTitle; - } - - function Title() { - return $this->addTitle ? $this->addTitle : parent::Title(); - } - - function ExtraData() { - $items = array(); - foreach($this->unpagedSourceItems as $item) { - if($item->{$this->joinField} == $this->controller->ID) - $items[] = $item->ID; - } - $list = implode(',', $items); - $inputId = $this->id() . '_' . $this->htmlListEndName; - return << -HTML; - } -} - -/** - * Single record of a {@link HasManyComplexTableField} field. - * @package forms - * @subpackage fields-relational - */ -class HasManyComplexTableField_Item extends ComplexTableField_Item { - - function MarkingCheckbox() { - $name = $this->parent->Name() . '[]'; - - $joinVal = $this->item->{$this->parent->joinField}; - $parentID = $this->parent->getControllerID(); - - if($this->parent->IsReadOnly || ($joinVal > 0 && $joinVal != $parentID)) - return "item->ID}\" disabled=\"disabled\"/>"; - else if($joinVal == $parentID) - return "item->ID}\" checked=\"checked\"/>"; - else - return "item->ID}\"/>"; - } -} - +Markable = true; + + $this->joinField = $this->getParentIdName($this->controller->ClassName, $this->sourceClass); + } + + function getQuery($limitClause = null) { + if($this->customQuery) { + $query = $this->customQuery; + $query->select[] = "{$this->sourceClass}.ID AS ID"; + $query->select[] = "{$this->sourceClass}.ClassName AS ClassName"; + $query->select[] = "{$this->sourceClass}.ClassName AS RecordClassName"; + } + else { + $query = singleton($this->sourceClass)->extendedSQL($this->sourceFilter, $this->sourceSort, $limitClause, $this->sourceJoin); + + // Add more selected fields if they are from joined table. + + $SNG = singleton($this->sourceClass); + foreach($this->FieldList() as $k => $title) { + if(! $SNG->hasField($k) && ! $SNG->hasMethod('get' . $k)) + $query->select[] = $k; + } + } + return clone $query; + } + + function sourceItems() { + if($this->sourceItems) + return $this->sourceItems; + + $limitClause = ''; + if(isset($_REQUEST[ 'ctf' ][ $this->Name() ][ 'start' ]) && is_numeric($_REQUEST[ 'ctf' ][ $this->Name() ][ 'start' ])) + $limitClause = $_REQUEST[ 'ctf' ][ $this->Name() ][ 'start' ] . ", $this->pageSize"; + else + $limitClause = "0, $this->pageSize"; + + $dataQuery = $this->getQuery($limitClause); + $records = $dataQuery->execute(); + $items = new DataObjectSet(); + foreach($records as $record) { + if(! get_class($record)) + $record = new DataObject($record); + $items->push($record); + } + + $dataQuery = $this->getQuery(); + $records = $dataQuery->execute(); + $unpagedItems = new DataObjectSet(); + foreach($records as $record) { + if(! get_class($record)) + $record = new DataObject($record); + $unpagedItems->push($record); + } + $this->unpagedSourceItems = $unpagedItems; + + $this->totalCount = ($this->unpagedSourceItems) ? $this->unpagedSourceItems->TotalItems() : null; + + return $items; + } + + function getControllerID() { + return $this->controller->ID; + } + + function saveInto(DataObject $record) { + $fieldName = $this->name; + $saveDest = $record->$fieldName(); + + if(! $saveDest) + user_error("HasManyComplexTableField::saveInto() Field '$fieldName' not found on $record->class.$record->ID", E_USER_ERROR); + + $items = array(); + + if($list = $this->value[ $this->htmlListField ]) { + if($list != 'undefined') + $items = explode(',', $list); + } + + $saveDest->setByIDList($items); + } + + function setAddTitle($addTitle) { + if(is_string($addTitle)) + $this->addTitle = $addTitle; + } + + function Title() { + return $this->addTitle ? $this->addTitle : parent::Title(); + } + + function ExtraData() { + $items = array(); + foreach($this->unpagedSourceItems as $item) { + if($item->{$this->joinField} == $this->controller->ID) + $items[] = $item->ID; + } + $list = implode(',', $items); + $inputId = $this->id() . '_' . $this->htmlListEndName; + return << +HTML; + } +} + +/** + * Single record of a {@link HasManyComplexTableField} field. + * @package forms + * @subpackage fields-relational + */ +class HasManyComplexTableField_Item extends ComplexTableField_Item { + + function MarkingCheckbox() { + $name = $this->parent->Name() . '[]'; + + $joinVal = $this->item->{$this->parent->joinField}; + $parentID = $this->parent->getControllerID(); + + if($this->parent->IsReadOnly || ($joinVal > 0 && $joinVal != $parentID)) + return "item->ID}\" disabled=\"disabled\"/>"; + else if($joinVal == $parentID) + return "item->ID}\" checked=\"checked\"/>"; + else + return "item->ID}\"/>"; + } +} + ?> \ No newline at end of file diff --git a/forms/HasOneComplexTableField.php b/forms/HasOneComplexTableField.php index 6adb89404..4b534ade2 100644 --- a/forms/HasOneComplexTableField.php +++ b/forms/HasOneComplexTableField.php @@ -1,74 +1,74 @@ -getParentIdNameRelation($parentClass, $childClass, 'has_one'); - } - - function getControllerJoinID() { - return $this->controller->{$this->joinField}; - } - - function saveInto(DataObject $record) { - $fieldName = $this->name; - $fieldNameID = $fieldName . 'ID'; - - $record->$fieldNameID = 0; - if($val = $this->value[ $this->htmlListField ]) { - if($val != 'undefined') - $record->$fieldNameID = $val; - } - - $record->write(); - } - - function setOneToOne() { - $this->isOneToOne = true; - } - - function isChildSet($childID) { - return DataObject::get($this->controller->ClassName, '`' . $this->joinField . "` = '$childID'"); - } - - function ExtraData() { - $val = $this->getControllerJoinID() ? $this->getControllerJoinID() : ''; - $inputId = $this->id() . '_' . $this->htmlListEndName; - return << -HTML; - } -} - -/** - * Single record of a {@link HasOneComplexTableField} field. - * @package forms - * @subpackage fields-relational - */ -class HasOneComplexTableField_Item extends ComplexTableField_Item { - - function MarkingCheckbox() { - $name = $this->parent->Name() . '[]'; - - $isOneToOne = $this->parent->isOneToOne; - $joinVal = $this->parent->getControllerJoinID(); - $childID = $this->item->ID; - - if($this->parent->IsReadOnly || ($isOneToOne && $joinVal != $childID && $this->parent->isChildSet($childID))) - return "item->ID}\" disabled=\"disabled\"/>"; - else if($joinVal == $childID) - return "item->ID}\" checked=\"checked\"/>"; - else - return "item->ID}\"/>"; - } -} - +getParentIdNameRelation($parentClass, $childClass, 'has_one'); + } + + function getControllerJoinID() { + return $this->controller->{$this->joinField}; + } + + function saveInto(DataObject $record) { + $fieldName = $this->name; + $fieldNameID = $fieldName . 'ID'; + + $record->$fieldNameID = 0; + if($val = $this->value[ $this->htmlListField ]) { + if($val != 'undefined') + $record->$fieldNameID = $val; + } + + $record->write(); + } + + function setOneToOne() { + $this->isOneToOne = true; + } + + function isChildSet($childID) { + return DataObject::get($this->controller->ClassName, '`' . $this->joinField . "` = '$childID'"); + } + + function ExtraData() { + $val = $this->getControllerJoinID() ? $this->getControllerJoinID() : ''; + $inputId = $this->id() . '_' . $this->htmlListEndName; + return << +HTML; + } +} + +/** + * Single record of a {@link HasOneComplexTableField} field. + * @package forms + * @subpackage fields-relational + */ +class HasOneComplexTableField_Item extends ComplexTableField_Item { + + function MarkingCheckbox() { + $name = $this->parent->Name() . '[]'; + + $isOneToOne = $this->parent->isOneToOne; + $joinVal = $this->parent->getControllerJoinID(); + $childID = $this->item->ID; + + if($this->parent->IsReadOnly || ($isOneToOne && $joinVal != $childID && $this->parent->isChildSet($childID))) + return "item->ID}\" disabled=\"disabled\"/>"; + else if($joinVal == $childID) + return "item->ID}\" checked=\"checked\"/>"; + else + return "item->ID}\"/>"; + } +} + ?> \ No newline at end of file diff --git a/forms/ManyManyComplexTableField.php b/forms/ManyManyComplexTableField.php index 0cd89d647..2f9a03625 100644 --- a/forms/ManyManyComplexTableField.php +++ b/forms/ManyManyComplexTableField.php @@ -1,105 +1,105 @@ -controller->ClassName)); - foreach($classes as $class) { - $singleton = singleton($class); - $manyManyRelations = $singleton->uninherited('many_many', true); - if(isset($manyManyRelations) && array_key_exists($this->name, $manyManyRelations)) { - $this->manyManyParentClass = $class; - $manyManyTable = $class . '_' . $this->name; - break; - } - $belongsManyManyRelations = $singleton->uninherited( 'belongs_many_many', true ); - if( isset( $belongsManyManyRelations ) && array_key_exists( $this->name, $belongsManyManyRelations ) ) { - $this->manyManyParentClass = $class; - $manyManyTable = $belongsManyManyRelations[$this->name] . '_' . $this->name; - break; - } - } - $tableClasses = ClassInfo::dataClassesFor($this->sourceClass); - $source = array_shift($tableClasses); - $sourceField = $this->sourceClass; - if($this->manyManyParentClass == $sourceField) - $sourceField = 'Child'; - $parentID = $this->controller->ID; - - $this->sourceJoin .= " LEFT JOIN `$manyManyTable` ON (`$source`.`ID` = `{$sourceField}ID` AND `{$this->manyManyParentClass}ID` = '$parentID')"; - - $this->joinField = 'Checked'; - } - - function getQuery($limitClause = null) { - if($this->customQuery) { - $query = $this->customQuery; - $query->select[] = "{$this->sourceClass}.ID AS ID"; - $query->select[] = "{$this->sourceClass}.ClassName AS ClassName"; - $query->select[] = "{$this->sourceClass}.ClassName AS RecordClassName"; - } - else { - $query = singleton($this->sourceClass)->extendedSQL($this->sourceFilter, $this->sourceSort, $limitClause, $this->sourceJoin); - - // Add more selected fields if they are from joined table. - - $SNG = singleton($this->sourceClass); - foreach($this->FieldList() as $k => $title) { - if(! $SNG->hasField($k) && ! $SNG->hasMethod('get' . $k)) - $query->select[] = $k; - } - $parent = $this->controller->ClassName; - $query->select[] = "IF(`{$this->manyManyParentClass}ID` IS NULL, '0', '1') AS Checked"; - } - return clone $query; - } - - function getParentIdName($parentClass, $childClass) { - return $this->getParentIdNameRelation($parentClass, $childClass, 'many_many'); - } - - function ExtraData() { - $items = array(); - foreach($this->unpagedSourceItems as $item) { - if($item->{$this->joinField}) - $items[] = $item->ID; - } - $list = implode(',', $items); - $inputId = $this->id() . '_' . $this->htmlListEndName; - return << -HTML; - } -} - -/** - * One record in a {@link ManyManyComplexTableField}. - * @package forms - * @subpackage fields-relational - */ -class ManyManyComplexTableField_Item extends ComplexTableField_Item { - - function MarkingCheckbox() { - $name = $this->parent->Name() . '[]'; - - if($this->parent->IsReadOnly) - return "item->ID}\" disabled=\"disabled\"/>"; - else if($this->item->{$this->parent->joinField}) - return "item->ID}\" checked=\"checked\"/>"; - else - return "item->ID}\"/>"; - } -} - -?> +controller->ClassName)); + foreach($classes as $class) { + $singleton = singleton($class); + $manyManyRelations = $singleton->uninherited('many_many', true); + if(isset($manyManyRelations) && array_key_exists($this->name, $manyManyRelations)) { + $this->manyManyParentClass = $class; + $manyManyTable = $class . '_' . $this->name; + break; + } + $belongsManyManyRelations = $singleton->uninherited( 'belongs_many_many', true ); + if( isset( $belongsManyManyRelations ) && array_key_exists( $this->name, $belongsManyManyRelations ) ) { + $this->manyManyParentClass = $class; + $manyManyTable = $belongsManyManyRelations[$this->name] . '_' . $this->name; + break; + } + } + $tableClasses = ClassInfo::dataClassesFor($this->sourceClass); + $source = array_shift($tableClasses); + $sourceField = $this->sourceClass; + if($this->manyManyParentClass == $sourceField) + $sourceField = 'Child'; + $parentID = $this->controller->ID; + + $this->sourceJoin .= " LEFT JOIN `$manyManyTable` ON (`$source`.`ID` = `{$sourceField}ID` AND `{$this->manyManyParentClass}ID` = '$parentID')"; + + $this->joinField = 'Checked'; + } + + function getQuery($limitClause = null) { + if($this->customQuery) { + $query = $this->customQuery; + $query->select[] = "{$this->sourceClass}.ID AS ID"; + $query->select[] = "{$this->sourceClass}.ClassName AS ClassName"; + $query->select[] = "{$this->sourceClass}.ClassName AS RecordClassName"; + } + else { + $query = singleton($this->sourceClass)->extendedSQL($this->sourceFilter, $this->sourceSort, $limitClause, $this->sourceJoin); + + // Add more selected fields if they are from joined table. + + $SNG = singleton($this->sourceClass); + foreach($this->FieldList() as $k => $title) { + if(! $SNG->hasField($k) && ! $SNG->hasMethod('get' . $k)) + $query->select[] = $k; + } + $parent = $this->controller->ClassName; + $query->select[] = "IF(`{$this->manyManyParentClass}ID` IS NULL, '0', '1') AS Checked"; + } + return clone $query; + } + + function getParentIdName($parentClass, $childClass) { + return $this->getParentIdNameRelation($parentClass, $childClass, 'many_many'); + } + + function ExtraData() { + $items = array(); + foreach($this->unpagedSourceItems as $item) { + if($item->{$this->joinField}) + $items[] = $item->ID; + } + $list = implode(',', $items); + $inputId = $this->id() . '_' . $this->htmlListEndName; + return << +HTML; + } +} + +/** + * One record in a {@link ManyManyComplexTableField}. + * @package forms + * @subpackage fields-relational + */ +class ManyManyComplexTableField_Item extends ComplexTableField_Item { + + function MarkingCheckbox() { + $name = $this->parent->Name() . '[]'; + + if($this->parent->IsReadOnly) + return "item->ID}\" disabled=\"disabled\"/>"; + else if($this->item->{$this->parent->joinField}) + return "item->ID}\" checked=\"checked\"/>"; + else + return "item->ID}\"/>"; + } +} + +?> diff --git a/forms/ToggleField.php b/forms/ToggleField.php index 643859014..5e7d218b0 100755 --- a/forms/ToggleField.php +++ b/forms/ToggleField.php @@ -1,100 +1,100 @@ -labelMore = _t('ToggleField.MORE', 'more'); - $this->labelLess = _t('ToggleField.LESS', 'less'); - - $this->startClosed(true); - - parent::__construct($name, $title, $value); - } - - function Field() { - $content = ''; - - Requirements::javascript("jsparty/prototype.js"); - Requirements::javascript("jsparty/behaviour.js"); - Requirements::javascript("jsparty/prototype_improvements.js"); - Requirements::javascript("sapphire/javascript/ToggleField.js"); - - if($this->startClosed) $this->addExtraClass('startClosed'); - - $valforInput = $this->value ? Convert::raw2att($this->value) : ""; - $rawInput = Convert::html2raw($valforInput); - - if($this->charNum) $reducedVal = substr($rawInput,0,$this->charNum); - else $reducedVal = DBField::create('Text',$rawInput)->{$this->truncateMethod}(); - - // only create togglefield if the truncated content is shorter - if(strlen($reducedVal) < strlen($rawInput)) { - $content = << - $reducedVal -  $this->labelMore - -
    - $this->value -  $this->labelLess -
    -
    - -HTML; - } else { - $this->dontEscape = true; - $content = parent::Field(); - } - - return $content; - } - - /** - * Determines if the field should render open or closed by default. - * - * @param boolean - */ - public function startClosed($bool) { - ($bool) ? $this->addExtraClass('startClosed') : $this->removeExtraClass('startClosed'); - } - - function Type() { - return "toggleField"; - } -} - +labelMore = _t('ToggleField.MORE', 'more'); + $this->labelLess = _t('ToggleField.LESS', 'less'); + + $this->startClosed(true); + + parent::__construct($name, $title, $value); + } + + function Field() { + $content = ''; + + Requirements::javascript("jsparty/prototype.js"); + Requirements::javascript("jsparty/behaviour.js"); + Requirements::javascript("jsparty/prototype_improvements.js"); + Requirements::javascript("sapphire/javascript/ToggleField.js"); + + if($this->startClosed) $this->addExtraClass('startClosed'); + + $valforInput = $this->value ? Convert::raw2att($this->value) : ""; + $rawInput = Convert::html2raw($valforInput); + + if($this->charNum) $reducedVal = substr($rawInput,0,$this->charNum); + else $reducedVal = DBField::create('Text',$rawInput)->{$this->truncateMethod}(); + + // only create togglefield if the truncated content is shorter + if(strlen($reducedVal) < strlen($rawInput)) { + $content = << + $reducedVal +  $this->labelMore + +
    + $this->value +  $this->labelLess +
    +
    + +HTML; + } else { + $this->dontEscape = true; + $content = parent::Field(); + } + + return $content; + } + + /** + * Determines if the field should render open or closed by default. + * + * @param boolean + */ + public function startClosed($bool) { + ($bool) ? $this->addExtraClass('startClosed') : $this->removeExtraClass('startClosed'); + } + + function Type() { + return "toggleField"; + } +} + ?> \ No newline at end of file diff --git a/lang/ru_RU.php b/lang/ru_RU.php index 5e988fe1e..50cec5bbf 100644 --- a/lang/ru_RU.php +++ b/lang/ru_RU.php @@ -244,7 +244,7 @@ $lang['ru_RU']['SiteTree']['METAPAGEPRIO'] = 'Приоритет страниц $lang['ru_RU']['SiteTree']['METATITLE'] = 'Заголовок'; $lang['ru_RU']['SiteTree']['MODIFIEDONDRAFT'] = 'Изменено на черновом сайте'; $lang['ru_RU']['SiteTree']['NOBACKLINKS'] = 'На эту страницу нет ссылок с других страниц'; -$lang['ru_RU']['SiteTree']['NOTEUSEASHOMEPAGE'] = 'Использовать эту страницу в качестве домашней для следующих доменов: +$lang['ru_RU']['SiteTree']['NOTEUSEASHOMEPAGE'] = 'Использовать эту страницу в качестве домашней для следующих доменов: (несколько доменов разделяйте запятыми)'; $lang['ru_RU']['SiteTree']['PAGESLINKING'] = 'На эту страницу ссылаются следующие страницы:'; $lang['ru_RU']['SiteTree']['PAGETITLE'] = 'Название страницы'; diff --git a/parsers/BBCodeParser.php b/parsers/BBCodeParser.php index 4237a4a55..7225d0534 100644 --- a/parsers/BBCodeParser.php +++ b/parsers/BBCodeParser.php @@ -1,116 +1,116 @@ - _t('BBCodeParser.BOLD', 'Bold Text'), - "Example" => '[b]'._t('BBCodeParser.BOLDEXAMPLE', 'Bold').'[/b]' - )), - new ArrayData(array( - "Title" => _t('BBCodeParser.ITALIC', 'Italic Text'), - "Example" => '[i]'._t('BBCodeParser.ITALICEXAMPLE', 'Italics').'[/i]' - )), - new ArrayData(array( - "Title" => _t('BBCodeParser.UNDERLINE', 'Underlined Text'), - "Example" => '[u]'._t('BBCodeParser.UNDERLINEEXAMPLE', 'Underlined').'[/u]' - )), - new ArrayData(array( - "Title" => _t('BBCodeParser.STRUCK', 'Struck-out Text'), - "Example" => '[s]'._t('BBCodeParser.STRUCKEXAMPLE', 'Struck-out').'[/s]' - )), - new ArrayData(array( - "Title" => _t('BBCodeParser.COLORED', 'Colored text'), - "Example" => '[color=blue]'._t('BBCodeParser.COLOREDEXAMPLE', 'blue text').'[/color]' - )), - new ArrayData(array( - "Title" => _t('BBCodeParser.ALIGNEMENT', 'Alignment'), - "Example" => '[align=right]'._t('BBCodeParser.ALIGNEMENTEXAMPLE', 'right aligned').'[/align]' - )), - - new ArrayData(array( - "Title" => _t('BBCodeParser.LINK', 'Website link'), - "Description" => _t('BBCodeParser.LINKDESCRIPTION', 'Link to another website or URL'), - "Example" => '[url]http://www.website.com/[/url]' - )), - new ArrayData(array( - "Title" => _t('BBCodeParser.LINK', 'Website link'), - "Description" => _t('BBCodeParser.LINKDESCRIPTION', 'Link to another website or URL'), - "Example" => "[url=http://www.website.com/]Some website[/url]" - )), - new ArrayData(array( - "Title" => _t('BBCodeParser.EMAILLINK', 'Email link'), - "Description" => _t('BBCodeParser.EMAILLINKDESCRIPTION', 'Create link to an email address'), - "Example" => "[email]you@yoursite.com[/email]" - )), - new ArrayData(array( - "Title" => _t('BBCodeParser.EMAILLINK', 'Email link'), - "Description" => _t('BBCodeParser.EMAILLINKDESCRIPTION', 'Create link to an email address'), - "Example" => "[email=you@yoursite.com]email me[/email]" - )), - - new ArrayData(array( - "Title" => _t('BBCodeParser.IMAGE', 'Image'), - "Description" => _t('BBCodeParser.IMAGEDESCRIPTION', 'Show an image in your post'), - "Example" => "[img]http://www.website.com/image.jpg[/img]" - )), - - new ArrayData(array( - "Title" => _t('BBCodeParser.CODE', 'Code Block'), - "Description" => _t('BBCodeParser.CODEDESCRIPTION', 'Unformatted code block'), - "Example" => '[code]'._t('BBCodeParser.CODEEXAMPLE', 'Code block').'[/code]' - )), - new ArrayData(array( - "Title" => _t('BBCodeParser.UNORDERED', 'Unordered list'), - "Description" => _t('BBCodeParser.UNORDEREDDESCRIPTION', 'Unordered list'), - "Example" => '[ulist][*]'._t('BBCodeParser.UNORDEREDEXAMPLE1', 'unordered item 1').'[*]'._t('BBCodeParser.UNORDEREDEXAMPLE2', 'unordered item 2').'[/ulist]' - )) - - - ); - } - - function useable_tagsHTML(){ - $useabletags = ""; - } - - function parse() { - $this->content = str_replace(array('&', '<', '>'), array('&', '<', '>'), $this->content); - $this->content = SSHTMLBBCodeParser::staticQparse($this->content); - $this->content = "

    ".$this->content."

    "; - $this->content = preg_replace("/\n\s*\n/", "

    ", $this->content); - $this->content = str_replace("\n", "
    ", $this->content); - return $this->content; - } - -} -?> + _t('BBCodeParser.BOLD', 'Bold Text'), + "Example" => '[b]'._t('BBCodeParser.BOLDEXAMPLE', 'Bold').'[/b]' + )), + new ArrayData(array( + "Title" => _t('BBCodeParser.ITALIC', 'Italic Text'), + "Example" => '[i]'._t('BBCodeParser.ITALICEXAMPLE', 'Italics').'[/i]' + )), + new ArrayData(array( + "Title" => _t('BBCodeParser.UNDERLINE', 'Underlined Text'), + "Example" => '[u]'._t('BBCodeParser.UNDERLINEEXAMPLE', 'Underlined').'[/u]' + )), + new ArrayData(array( + "Title" => _t('BBCodeParser.STRUCK', 'Struck-out Text'), + "Example" => '[s]'._t('BBCodeParser.STRUCKEXAMPLE', 'Struck-out').'[/s]' + )), + new ArrayData(array( + "Title" => _t('BBCodeParser.COLORED', 'Colored text'), + "Example" => '[color=blue]'._t('BBCodeParser.COLOREDEXAMPLE', 'blue text').'[/color]' + )), + new ArrayData(array( + "Title" => _t('BBCodeParser.ALIGNEMENT', 'Alignment'), + "Example" => '[align=right]'._t('BBCodeParser.ALIGNEMENTEXAMPLE', 'right aligned').'[/align]' + )), + + new ArrayData(array( + "Title" => _t('BBCodeParser.LINK', 'Website link'), + "Description" => _t('BBCodeParser.LINKDESCRIPTION', 'Link to another website or URL'), + "Example" => '[url]http://www.website.com/[/url]' + )), + new ArrayData(array( + "Title" => _t('BBCodeParser.LINK', 'Website link'), + "Description" => _t('BBCodeParser.LINKDESCRIPTION', 'Link to another website or URL'), + "Example" => "[url=http://www.website.com/]Some website[/url]" + )), + new ArrayData(array( + "Title" => _t('BBCodeParser.EMAILLINK', 'Email link'), + "Description" => _t('BBCodeParser.EMAILLINKDESCRIPTION', 'Create link to an email address'), + "Example" => "[email]you@yoursite.com[/email]" + )), + new ArrayData(array( + "Title" => _t('BBCodeParser.EMAILLINK', 'Email link'), + "Description" => _t('BBCodeParser.EMAILLINKDESCRIPTION', 'Create link to an email address'), + "Example" => "[email=you@yoursite.com]email me[/email]" + )), + + new ArrayData(array( + "Title" => _t('BBCodeParser.IMAGE', 'Image'), + "Description" => _t('BBCodeParser.IMAGEDESCRIPTION', 'Show an image in your post'), + "Example" => "[img]http://www.website.com/image.jpg[/img]" + )), + + new ArrayData(array( + "Title" => _t('BBCodeParser.CODE', 'Code Block'), + "Description" => _t('BBCodeParser.CODEDESCRIPTION', 'Unformatted code block'), + "Example" => '[code]'._t('BBCodeParser.CODEEXAMPLE', 'Code block').'[/code]' + )), + new ArrayData(array( + "Title" => _t('BBCodeParser.UNORDERED', 'Unordered list'), + "Description" => _t('BBCodeParser.UNORDEREDDESCRIPTION', 'Unordered list'), + "Example" => '[ulist][*]'._t('BBCodeParser.UNORDEREDEXAMPLE1', 'unordered item 1').'[*]'._t('BBCodeParser.UNORDEREDEXAMPLE2', 'unordered item 2').'[/ulist]' + )) + + + ); + } + + function useable_tagsHTML(){ + $useabletags = "

    "; + } + + function parse() { + $this->content = str_replace(array('&', '<', '>'), array('&', '<', '>'), $this->content); + $this->content = SSHTMLBBCodeParser::staticQparse($this->content); + $this->content = "

    ".$this->content."

    "; + $this->content = preg_replace("/\n\s*\n/", "

    ", $this->content); + $this->content = str_replace("\n", "
    ", $this->content); + return $this->content; + } + +} +?> diff --git a/parsers/TextParser.php b/parsers/TextParser.php index dce3f2301..867417dca 100644 --- a/parsers/TextParser.php +++ b/parsers/TextParser.php @@ -1,53 +1,53 @@ -content and parse it however you want. For an example - * of the implementation, @see BBCodeParser. - * - * Your sub-class will be initialized with a string of text, then parse() will be called. - * parse() should (after processing) return the formatted string. - * - * Note: $this->content will have NO conversions applied to it. - * You should run Covert::raw2xml or whatever is appropriate before using it. - * - * Optionally (but recommended), is creating a static usable_tags method, - * which will return a DataObjectSet of all the usable tags that can be parsed. - * This will (mostly) be used to create helper blocks - telling users what things will be parsed. - * Again, @see BBCodeParser for an example of the syntax - * - * @todo Define a proper syntax for (or refactor) usable_tags that can be extended as needed. - * @package sapphire - * @subpackage misc - */ -abstract class TextParser extends Object { - protected $content; - - /** - * Creates a new TextParser object. - * - * @param string $content The contents of the dbfield - */ - function __construct($content = "") { - $this->content = $content; - } - - /** - * Convenience method, shouldn't really be used, but it's here if you want it - */ - function setContent($content = "") { - $this->content = $content; - } - - /** - * Define your own parse method to parse $this->content appropriately. - * See the class doc-block for more implementation details. - */ - abstract function parse(); -} +content and parse it however you want. For an example + * of the implementation, @see BBCodeParser. + * + * Your sub-class will be initialized with a string of text, then parse() will be called. + * parse() should (after processing) return the formatted string. + * + * Note: $this->content will have NO conversions applied to it. + * You should run Covert::raw2xml or whatever is appropriate before using it. + * + * Optionally (but recommended), is creating a static usable_tags method, + * which will return a DataObjectSet of all the usable tags that can be parsed. + * This will (mostly) be used to create helper blocks - telling users what things will be parsed. + * Again, @see BBCodeParser for an example of the syntax + * + * @todo Define a proper syntax for (or refactor) usable_tags that can be extended as needed. + * @package sapphire + * @subpackage misc + */ +abstract class TextParser extends Object { + protected $content; + + /** + * Creates a new TextParser object. + * + * @param string $content The contents of the dbfield + */ + function __construct($content = "") { + $this->content = $content; + } + + /** + * Convenience method, shouldn't really be used, but it's here if you want it + */ + function setContent($content = "") { + $this->content = $content; + } + + /** + * Define your own parse method to parse $this->content appropriately. + * See the class doc-block for more implementation details. + */ + abstract function parse(); +} ?> \ No newline at end of file diff --git a/security/MemberLoginForm.php b/security/MemberLoginForm.php index e8e8efa21..54f618a65 100644 --- a/security/MemberLoginForm.php +++ b/security/MemberLoginForm.php @@ -1,207 +1,207 @@ -authenticator_class = 'MemberAuthenticator'; - - $customCSS = project() . '/css/member_login.css'; - if(Director::fileExists($customCSS)) { - Requirements::css($customCSS); - } - - if(isset($_REQUEST['BackURL'])) { - $backURL = $_REQUEST['BackURL']; - } else { - $backURL = Session::get('BackURL'); - } - - if($checkCurrentUser && Member::currentUserID()) { - $fields = new FieldSet(); - $actions = new FieldSet(new FormAction("logout", _t('Member.BUTTONLOGINOTHER', "Log in as someone else"))); - } else { - if(!$fields) { - $fields = new FieldSet( - new HiddenField("AuthenticationMethod", null, $this->authenticator_class, $this), - new TextField("Email", _t('Member.EMAIL'), - Session::get('SessionForms.MemberLoginForm.Email'), null, $this), - new EncryptField("Password", _t('Member.PASSWORD'), null, $this), - new CheckboxField("Remember", _t('Member.REMEMBERME', "Remember me next time?"), - Session::get('SessionForms.MemberLoginForm.Remember'), $this) - ); - } - if(!$actions) { - $actions = new FieldSet( - new FormAction("dologin", _t('Member.BUTTONLOGIN', "Log in")), - new FormAction("forgotPassword", _t('Member.BUTTONLOSTPASSWORD', "I've lost my password")) - ); - } - } - - if(isset($backURL)) { - $fields->push(new HiddenField('BackURL', 'BackURL', $backURL)); - } - - parent::__construct($controller, $name, $fields, $actions); - } - - - /** - * Get message from session - */ - protected function getMessageFromSession() { - parent::getMessageFromSession(); - if(($member = Member::currentUser()) && - !Session::get('MemberLoginForm.force_message')) { - $this->message = sprintf(_t('Member.LOGGEDINAS', "You're logged in as %s."), $member->FirstName); - } - Session::set('MemberLoginForm.force_message', false); - } - - - /** - * Login form handler method - * - * This method is called when the user clicks on "Log in" - * - * @param array $data Submitted data - */ - public function dologin($data) { - if($this->performLogin($data)) { - Session::clear('SessionForms.MemberLoginForm.Email'); - Session::clear('SessionForms.MemberLoginForm.Remember'); - - if(Member::currentUser()->isPasswordExpired()) { - if(isset($_REQUEST['BackURL']) && $backURL = $_REQUEST['BackURL']) { - Session::set('BackURL', $backURL); - } - - $cp = new ChangePasswordForm($this->controller, 'ChangePasswordForm'); - $cp->sessionMessage('Your password has expired. Please choose a new one.', 'good'); - - Director::redirect('Security/changepassword'); - - - } else if(isset($_REQUEST['BackURL']) && $backURL = $_REQUEST['BackURL']) { - Session::clear("BackURL"); - Director::redirect($backURL); - } else { - Director::redirect(Security::default_login_dest()); - } - } else { - Session::set('SessionForms.MemberLoginForm.Email', $data['Email']); - Session::set('SessionForms.MemberLoginForm.Remember', isset($data['Remember'])); - - if(isset($_REQUEST['BackURL']) && $backURL = $_REQUEST['BackURL']) { - Session::set('BackURL', $backURL); - } - - if($badLoginURL = Session::get("BadLoginURL")) { - Director::redirect($badLoginURL); - } else { - // Show the right tab on failed login - Director::redirect(Director::absoluteURL(Security::Link("login")) . - '#' . $this->FormName() .'_tab'); - } - } - } - - - /** - * Log out form handler method - * - * This method is called when the user clicks on "logout" on the form - * created when the parameter $checkCurrentUser of the - * {@link __construct constructor} was set to TRUE and the user was - * currently logged in. - */ - public function logout() { - $s = new Security(); - $s->logout(); - } - - - /** - * Try to authenticate the user - * - * @param array Submitted data - * @return Member Returns the member object on successful authentication - * or NULL on failure. - */ - public function performLogin($data) { - if($member = MemberAuthenticator::authenticate($data, $this)) { - $firstname = Convert::raw2xml($member->FirstName); - Session::set("Security.Message.message", - sprintf(_t('Member.WELCOMEBACK', "Welcome Back, %s"), $firstname) - ); - Session::set("Security.Message.type", "good"); - - $member->LogIn(isset($data['Remember'])); - return $member; - - } else { - $this->extend('authenticationFailed', $data); - return null; - } - } - - - /** - * Forgot password form handler method - * - * This method is called when the user clicks on "I've lost my password" - * - * @param array $data Submitted data - */ - function forgotPassword($data) { - $SQL_data = Convert::raw2sql($data); - - if(($data['Email']) && ($member = DataObject::get_one("Member", - "Member.Email = '$SQL_data[Email]'"))) { - - $member->generateAutologinHash(); - - $member->sendInfo('forgotPassword', array('PasswordResetLink' => - Security::getPasswordResetLink($member->AutoLoginHash))); - - Director::redirect('Security/passwordsent/?email=' . urlencode($data['Email'])); - - } else if($data['Email']) { - $this->sessionMessage( - _t('Member.ERRORSIGNUP', "Sorry, but I don't recognise the e-mail address. Maybe you need " . - "to sign up, or perhaps you used another e-mail address?"), - "bad"); - Director::redirectBack(); - - } else { - Director::redirect("Security/lostpassword"); - } - } - -} - - -?> +authenticator_class = 'MemberAuthenticator'; + + $customCSS = project() . '/css/member_login.css'; + if(Director::fileExists($customCSS)) { + Requirements::css($customCSS); + } + + if(isset($_REQUEST['BackURL'])) { + $backURL = $_REQUEST['BackURL']; + } else { + $backURL = Session::get('BackURL'); + } + + if($checkCurrentUser && Member::currentUserID()) { + $fields = new FieldSet(); + $actions = new FieldSet(new FormAction("logout", _t('Member.BUTTONLOGINOTHER', "Log in as someone else"))); + } else { + if(!$fields) { + $fields = new FieldSet( + new HiddenField("AuthenticationMethod", null, $this->authenticator_class, $this), + new TextField("Email", _t('Member.EMAIL'), + Session::get('SessionForms.MemberLoginForm.Email'), null, $this), + new EncryptField("Password", _t('Member.PASSWORD'), null, $this), + new CheckboxField("Remember", _t('Member.REMEMBERME', "Remember me next time?"), + Session::get('SessionForms.MemberLoginForm.Remember'), $this) + ); + } + if(!$actions) { + $actions = new FieldSet( + new FormAction("dologin", _t('Member.BUTTONLOGIN', "Log in")), + new FormAction("forgotPassword", _t('Member.BUTTONLOSTPASSWORD', "I've lost my password")) + ); + } + } + + if(isset($backURL)) { + $fields->push(new HiddenField('BackURL', 'BackURL', $backURL)); + } + + parent::__construct($controller, $name, $fields, $actions); + } + + + /** + * Get message from session + */ + protected function getMessageFromSession() { + parent::getMessageFromSession(); + if(($member = Member::currentUser()) && + !Session::get('MemberLoginForm.force_message')) { + $this->message = sprintf(_t('Member.LOGGEDINAS', "You're logged in as %s."), $member->FirstName); + } + Session::set('MemberLoginForm.force_message', false); + } + + + /** + * Login form handler method + * + * This method is called when the user clicks on "Log in" + * + * @param array $data Submitted data + */ + public function dologin($data) { + if($this->performLogin($data)) { + Session::clear('SessionForms.MemberLoginForm.Email'); + Session::clear('SessionForms.MemberLoginForm.Remember'); + + if(Member::currentUser()->isPasswordExpired()) { + if(isset($_REQUEST['BackURL']) && $backURL = $_REQUEST['BackURL']) { + Session::set('BackURL', $backURL); + } + + $cp = new ChangePasswordForm($this->controller, 'ChangePasswordForm'); + $cp->sessionMessage('Your password has expired. Please choose a new one.', 'good'); + + Director::redirect('Security/changepassword'); + + + } else if(isset($_REQUEST['BackURL']) && $backURL = $_REQUEST['BackURL']) { + Session::clear("BackURL"); + Director::redirect($backURL); + } else { + Director::redirect(Security::default_login_dest()); + } + } else { + Session::set('SessionForms.MemberLoginForm.Email', $data['Email']); + Session::set('SessionForms.MemberLoginForm.Remember', isset($data['Remember'])); + + if(isset($_REQUEST['BackURL']) && $backURL = $_REQUEST['BackURL']) { + Session::set('BackURL', $backURL); + } + + if($badLoginURL = Session::get("BadLoginURL")) { + Director::redirect($badLoginURL); + } else { + // Show the right tab on failed login + Director::redirect(Director::absoluteURL(Security::Link("login")) . + '#' . $this->FormName() .'_tab'); + } + } + } + + + /** + * Log out form handler method + * + * This method is called when the user clicks on "logout" on the form + * created when the parameter $checkCurrentUser of the + * {@link __construct constructor} was set to TRUE and the user was + * currently logged in. + */ + public function logout() { + $s = new Security(); + $s->logout(); + } + + + /** + * Try to authenticate the user + * + * @param array Submitted data + * @return Member Returns the member object on successful authentication + * or NULL on failure. + */ + public function performLogin($data) { + if($member = MemberAuthenticator::authenticate($data, $this)) { + $firstname = Convert::raw2xml($member->FirstName); + Session::set("Security.Message.message", + sprintf(_t('Member.WELCOMEBACK', "Welcome Back, %s"), $firstname) + ); + Session::set("Security.Message.type", "good"); + + $member->LogIn(isset($data['Remember'])); + return $member; + + } else { + $this->extend('authenticationFailed', $data); + return null; + } + } + + + /** + * Forgot password form handler method + * + * This method is called when the user clicks on "I've lost my password" + * + * @param array $data Submitted data + */ + function forgotPassword($data) { + $SQL_data = Convert::raw2sql($data); + + if(($data['Email']) && ($member = DataObject::get_one("Member", + "Member.Email = '$SQL_data[Email]'"))) { + + $member->generateAutologinHash(); + + $member->sendInfo('forgotPassword', array('PasswordResetLink' => + Security::getPasswordResetLink($member->AutoLoginHash))); + + Director::redirect('Security/passwordsent/?email=' . urlencode($data['Email'])); + + } else if($data['Email']) { + $this->sessionMessage( + _t('Member.ERRORSIGNUP', "Sorry, but I don't recognise the e-mail address. Maybe you need " . + "to sign up, or perhaps you used another e-mail address?"), + "bad"); + Director::redirectBack(); + + } else { + Director::redirect("Security/lostpassword"); + } + } + +} + + +?>