예제 #1
0
 /**
  * Constructor Method
  * @param int $type (required) -
  * @param string $name (required) -
  * @param string $user (required for secured) -
  * @param string $pass (required for secured) -
  * @param string $host (required for remote, optional because it defaults to localhost) -
  * @param integer $port (required for remote, optional because it defaults to server type's default port) -
  * @param strign $table (optional) -
  */
 public function __construct($name, $user = null, $pass = null, $host = 'localhost', $port = null, $table = null)
 {
     $data = [];
     //instantiate data array
     /*
      * Input Handling for $name (database name)
      *
      * $name is required, must be a string, and must be a valid database name,
      * but we cannot check if it's a valid name until we connect.
      */
     if (isset($name)) {
         //database name is set
         if (gettype($name) != 'string') {
             //database name is not a string
             throw new DatabaseException(__METHOD__ . '(): encountered database name argument of invalid type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this);
         } else {
             $data['name'] = $name;
             //add validated database name to data array
         }
     } else {
         //database name is not set
         throw new DatabaseException(__METHOD__ . '(): missing required database name argument.', DatabaseException::EXCEPTION_MISSING_REQUIRED_ARGUMENT, $this);
     }
     /*
      * Input Handling for $user (username)
      *
      * $user is only required for servers that require authentication. We cannot
      * test if authentication is required until after connecting. $user also must
      * be a string.
      */
     if ($user !== null) {
         //username is set
         if (gettype($user) != 'string') {
             //username is not a string
             throw new DatabaseException(__METHOD__ . '(): encountered username argument of invalid type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this);
         } else {
             $data['user'] = $user;
             //add validated username to data array
         }
     }
     /*
      * Input Handling for $pass (password)
      *
      * $pass is only required for servers that require authentication. We cannot
      * test if authentication is required until after connecting. $pass also must
      * be a string.
      */
     if ($pass !== null) {
         //password is set
         if (gettype($pass) != 'string') {
             //password is not a string
             throw new DatabaseException(__METHOD__ . '(): encountered password argument of invalid type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this);
         } else {
             $data['pass'] = $pass;
             //add validated password to data array
         }
     }
     /*
      * Input Handling for $host (server hostname)
      *
      * $host is only required for remote database servers (so not sqlite). However,
      * $host already has a default value of 'localhost', which means that it doesn't
      * have to be provided in an argument if using localhost. $host must be a string,
      * $host must be a valid IP address, hostname, or domain name, and if there is a
      * port after a : in the URL, that must be separated into $port.
      */
     if ($host != 'localhost') {
         //hostname is set
         if (gettype($host) == 'string') {
             //hostname is a string
             if (!DatabaseUtils::isValidHost($host)) {
                 //hostname has invalid syntax
                 throw new DatabaseException(__METHOD__ . '(): encountered invalid given hostname (do not include URI scheme, port numbers, or paths!).', DatabaseException::EXCEPTION_INPUT_NOT_VALID, $this);
             } else {
                 $data['host'] = $host;
                 //add validated hostname to data array
             }
         } else {
             //hostname is not a string
             throw new DatabaseException(__METHOD__ . '(): encountered hostname argument of invalid type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this);
         }
     } else {
         $data['host'] = $host;
         //add default hostname to data array
     }
     /*
      * Input Handling for $port (server port number)
      *
      * $port is only required for remote database servers (so not sqlite). However,
      * $port will be given a default value based on the server type. $port must be an
      * integer greater than or equal to 0 and less than or equal to 65535. The actual
      * validity of the port cannot be validated until trying to connect to the server.
      */
     if ($port !== null) {
         //port is set
         if (!is_int($port)) {
             //port is not an integer
             if (is_numeric($port)) {
                 $port = (int) $port;
                 if (0 > $port || $port > 65535) {
                     throw new DatabaseException(__METHOD__ . '(): encountered port number argument outside of legal bounds.', DatabaseException::EXCEPTION_INPUT_NOT_VALID, $this);
                 } else {
                     $data['port'] = $port;
                     //add validated password to data array
                 }
             } else {
                 throw new DatabaseException(__METHOD__ . '(): encountered port number argument of invalid type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this);
             }
         }
     } else {
         //port is not set
         $port = isset($this->dbms['config']['defaultPort']) ? $this->dbms['config']['defaultPort'] : null;
         //no port available
         $data['port'] = $port;
         //add validated port number to data array
     }
     /*
      * Input Handling for $table (default table)
      *
      * $table is optional. This only has to be set when a default table is required.
      * If it is not set, other methods will need to be given a table argument or they will
      * error. Table must be a string, and must be a valid name for a SQL table. We won't know
      * if the default table is valid until after the database connection is established, but
      * it will be tested then.
      */
     if ($table !== null) {
         //table is set
         if (gettype($table) != 'string') {
             //table is not a string
             throw new DatabaseException(__METHOD__ . '(): encountered table argument of invalid type.', DatabaseException::EXCEPTION_INPUT_INVALID_TYPE, $this);
         } else {
             $data['table'] = $table;
         }
     } else {
         $data['table'] = $table;
     }
     //Set class properties/members
     $this->name = $data['name'];
     $this->user = $data['user'];
     $this->pass = $data['pass'];
     $this->host = $data['host'];
     $this->port = $data['port'];
     $this->table = $data['table'];
     //generate DSN
     $dsn = $this->dbms['dsn']['prefix'] . ':';
     //add prefix
     $dsnargs = [];
     //instantiate dsn arguments array
     foreach ($this->dbms['dsn']['args'] as $arg) {
         //loop over each argument
         if ($arg['required']) {
             //check if argument is required
             if (!isset($data[$arg['value']]) || $data[$arg['value']] == null) {
                 //check if required argument is missing
                 throw new DatabaseException(__METHOD__ . '(): missing required argument "' . $arg['value'] . '" to build DSN.' . json_encode($data), DatabaseException::EXCEPTION_MISSING_REQUIRED_ARGUMENT, $this);
                 continue;
                 //skip iteration (in case exception is caught)
             }
         }
         //create DSN argument and insert it into argument array
         if (isset($arg['name']) && $arg['name'] != null) {
             //if argument has a name...
             $dsnargs[] = $arg['name'] . '=' . str_replace(';', '', $data[$arg['value']]);
             //format like "name=value"...
         } else {
             //if argument has no name...
             $dsnargs[] = str_replace(';', '', $data[$arg['value']]);
             //format like "value".
         }
     }
     $dsn .= implode(';', $dsnargs);
     //combine all arguments, separate with ';', add to DSN
     //create PDO object with DSN (this is the actual connection)
     try {
         $this->connector = new PDO($dsn, $user, $pass);
         $this->connector->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
         $this->connector->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
     } catch (PDOException $e) {
         throw new DatabaseException(__METHOD__ . '(): caught exception when opening the database connection', DatabaseException::EXCEPTION_GENERIC_DATABASE_ERROR, $this, $e);
     }
 }