diff --git a/src/MetaTech/Core/Singleton.php b/src/MetaTech/Core/Singleton.php new file mode 100644 index 0000000..cec918b --- /dev/null +++ b/src/MetaTech/Core/Singleton.php @@ -0,0 +1,48 @@ +getName(); + if ($recreate || !isset($this->conn[$name]) || $this->conn[$name] == null) { + $this->setPdo($profile); + } + return $this->conn[$name]; + } + + /*! + * @method setCurrentProfile + * @private + * @param str $name + */ + private function setCurrentProfile($name) + { + $this->currentProfile = $name; + } + + /*! + * @method setPdo + * @private + * @param MetaTech\Db\Profile $profile + */ + private function setPdo(Profile $profile) + { + $pdo = new PDO($profile->getDsn(), $profile->getUser(), $profile->getPassword()); + $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $pdo->query("SET NAMES '".$profile->getCharset()."'"); + $this->conn[$profile->getName()] = $pdo; + } + + /*! + * @method switchDb + * @public + * @param MetaTech\Db\Profile $profile + * @param bool $recreate + */ + public function switchDb(Profile $profile, $recreate=false) + { + $this->currentProfile = $profile->getName(); + $this->getPdo($profile, $recreate); + } + + /*! + * @method conn + * @public + * @return PDO + */ + public function conn() + { + return $this->conn[$this->currentProfile]; + } +} diff --git a/src/MetaTech/Db/PdoWrapper.php b/src/MetaTech/Db/PdoWrapper.php new file mode 100644 index 0000000..80a96a0 --- /dev/null +++ b/src/MetaTech/Db/PdoWrapper.php @@ -0,0 +1,234 @@ +profile = $profile; + $this->logger = $logger; + } + + /*! + * Return the PDO connection object + * + * @method getPdoConnection + * @public + * @return PDO + */ + public function getPdoConnection() + { + return PdoConnector::getInstance()->conn(); + } + + /*! + * @method switchDb + * @public + * @param Mtc\Core\Db\Profile $profile + * @return PDO + */ + public function switchDb(Profile $profile = null, $recreate=false) + { + if (is_null($profile)) { + $profile = $this->profile; + } + return PdoConnector::getInstance()->switchDb($profile, $recreate); + } + + /*! + * @method getLogger + * @public + * @return Monolog\Handler\StreamHandler + */ + public function getLogger() + { + return $this->logger; + } + + /*! + * @method log + * @private + * @param str $query + * @param [] $data + * @param bool $start + */ + private function log($query, $data, $start=true, $forceLog=false) + { + if ($this->logger != null) { + $minisql = substr($query, 0, 35); + $bypasslog = strpos(substr($query, 0, 35), 'SELECT')!==false; + if (!$this->bypasslog || $forceLog) { + $this->bypasslog = $bypasslog; + if ($start) { + if (!$bypasslog || $forceLog) { + $this->logger->addDebug(" => ".str_pad("QUERY", 8, " ", STR_PAD_LEFT).' '.preg_replace('/[ ]{2,}/', ' ', $query)); + if( !empty($data)) $this->logger->addDebug(str_pad("PARAMS", 12, " ", STR_PAD_LEFT), $data); + } + } + else { + $this->logger->addDebug(" <= $query", $data); + } + } + elseif (!$start) $this->bypasslog = false; + } + } + + /*! + * execute a query and get Result Statement for the specified $data + * + * @method exec + * @public + * @param str $query + * @param [] $data + * @param int $fetch + * @return PdoStatement + */ + public function exec($query, $data = array(), $fetch = null, $forceLog=false) + { + $this->switchDb(null, true); + $this->log($query, $data, true, $forceLog); + if ($fetch == null) { + $fetch = \PDO::FETCH_OBJ; + } + $stmt = $this->getPdoConnection()->prepare($query); + if (is_array($data)) { + foreach ($data as $cl => $f) { + if (!is_null($f)) { + @$stmt->bindParam(':'.$cl, $data[$cl], ($cl == 'queryIndex' || $cl == 'queryLimit' ? \PDO::PARAM_INT : \PDO::PARAM_STR)); // don't use $f, cause value pass by reference + } + else { + $stmt->bindValue(':'.$cl, null, \PDO::PARAM_INT /* prefer to \PDO::PARAM_NULL for compat*/); + } + } + } + try { + $stmt->execute(); + if ($fetch !== false) { + $stmt->setFetchMode($fetch); + } + $rowCount = $stmt!=null ? $stmt->rowCount() : 0; + $lastInsertId = $this->getLastInsertId(); + + $this->log(str_pad("RS", 8, " ", STR_PAD_LEFT), compact('rowCount', 'lastInsertId'), false, $forceLog); + } + catch(\Exception $e) { + if (!is_null($this->logger)) { + $this->bypasslog = false; + $this->logger->addError($e->getMessage()); + foreach (preg_split('/#/', $e->getTraceAsString()) as $error) { + if (!empty($error)) { + $this->logger->addDebug("#$error"); + } + } + } + throw $e; + } + return $stmt; + } + + /*! + * get last insert id in db + * + * @method getLastInsertId + * @public + * @return int + */ + public function getLastInsertId() + { + return $this->getPdoConnection()->lastInsertId(); + } + + /*! + * persist $data in table $table + * + * @method persist + * @public + * @param str $table + * @param [] $data + * @param bool $updateOnDuplicate + * @return PdoStatement + */ + public function persist($table, $data, $updateOnDuplicate = true) + { + if (isset($data['id']) && is_null($data['id'])) { + unset($data['id']); + $updateOnDuplicate = false; + } + $argnames = array_keys($data); + $updateDef = ''; + if ($updateOnDuplicate) { + foreach ($argnames as $field) { + $updateDef .= ($updateDef == '' ? '' : ',')." `$field` = VALUES(`$field`)"; + } + $updateDef = "ON DUPLICATE KEY UPDATE $updateDef"; + } + return $this->exec( + "INSERT INTO $table (`".implode('`, `', $argnames).'`) VALUES (:'.implode(', :', $argnames).") $updateDef", + $data + ); + } + + /*! + * get autoincrement + * + * @method nextIncrement + * @public + * @param str $table + * @return int + */ + public function nextIncrement($table) + { + $data = $this->exec('SHOW TABLE STATUS WHERE `Name`= :table', compact('table'))->fetch(); + return $data != false ? $data->Auto_increment : null; + } + + /*! + * @method encodeJsonBase64 + * @public + * @static + * @param mixed $data + * @return str + */ + public static function encodeJsonBase64($data) + { + return base64_encode(json_encode($data)); + } + + /*! + * @method decodeJsonBase64 + * @public + * @static + * @param str $data + * @param bool $onlyb64 + * @return stdclass + */ + public static function decodeJsonBase64($data, $onlyb64 = false) + { + return $onlyb64 ? base64_decode($data) : json_decode(base64_decode($data)); + } + +} diff --git a/src/MetaTech/Db/Profile.php b/src/MetaTech/Db/Profile.php new file mode 100644 index 0000000..8948cca --- /dev/null +++ b/src/MetaTech/Db/Profile.php @@ -0,0 +1,79 @@ +config = $config; + } else { + throw new \Exception("$config must be associative array"); + } + } + /*! + * @method getName + * @public + * @return str + */ + public function getName() + { + return !isset($this->config['name']) ? $this->config['dbname'] : $this->config['name']; + } + + /*! + * @method getUser + * @public + * @return str + */ + public function getUser() + { + return $this->config['user']; + } + + /*! + * @method getPassword + * @public + * @return str + */ + public function getPassword() + { + return $this->config['password']; + } + + /*! + * @method getCharset + * @public + * @return str + */ + public function getCharset() + { + return $this->config['charset']; + } + + /*! + * @method getDsn + * @public + * @return str + */ + public function getDsn() + { + return 'mysql:host='.$this->config['host'].';port=3306;dbname='.$this->config['dbname']; + } +} diff --git a/src/MetaTech/Silex/Provider/UserProvider.php b/src/MetaTech/Silex/Provider/UserProvider.php new file mode 100644 index 0000000..0578d58 --- /dev/null +++ b/src/MetaTech/Silex/Provider/UserProvider.php @@ -0,0 +1,159 @@ +pdo = $pdo; + $this->table = $table; + } + + /*! + * @method loadUser + * @private + * @param str $login + * @return Symfony\Component\Security\Core\User\User + */ + private function loadUser($login) + { + $username = strtolower($login); + $stmt = $this->pdo->exec('SELECT * FROM ' . $this->table . ' WHERE username = :username', compact('username')); + if (!$user = $stmt->fetch()) { + throw new UsernameNotFoundException(sprintf('Username "%s" does not exist.', $username)); + } + return $user; + } + + /*! + * @method getUserNameById + * @public + * @param int $id + * @return Symfony\Component\Security\Core\User\User + */ + public function getUserNameById($id) + { + $stmt = $this->pdo->exec('SELECT name FROM ' . $this->table . ' WHERE id = :id', compact('id')); + if (!$user = $stmt->fetch()) { + throw new UsernameNotFoundException(sprintf('Userid "%s" does not exist.', $id)); + } + return $user; + } + + /*! + * @method loadUserPrograms + * @public + * @return Symfony\Component\Security\Core\User\User + */ + private function loadUserByRole($role) + { + return $this->pdo->exec('SELECT * FROM ' . $this->table . ' WHERE roles LIKE :role', compact('role'))->fetchAll(); + } + + /*! + * @method loadProgramKeys + * @public + * @return Symfony\Component\Security\Core\User\User + */ + public function loadProgramKeys() + { + $keys = []; + $rows = $this->loadUserPrograms(); + $rows = array_merge($rows, $this->loadUserPrograms('INSURER')); + if (!empty($rows)) { + foreach ($rows as $row) { + $keys[] = $row->key; + } + } + return $keys; + } + + /*! + * @method loadUserByUsername + * @public + * @param str $username + * @return Symfony\Component\Security\Core\User\User + */ + public function loadUserByUsername($username) + { + $user = $this->loadUser($username); + $u = new User($user->username, $user->password, explode(',', $user->roles), true, true, true, true); + $u->labelName = $user->name; + return $u; + } + + /*! + * @method getUserKey + * @public + * @param str $username + * @return Symfony\Component\Security\Core\User\User + */ + public function getUserKey($username) + { + $user = $this->loadUser($username); + return $user->key; + } + + /*! + * @method getIdUser + * @public + * @param str $username + * @return int|null + */ + public function getIdUser($username) + { + $user = $this->loadUser($username); + return isset($user->id) ? $user->id : null; + } + + /*! + * @method refreshUser + * @public + * @param Symfony\Component\Security\Core\User\UserInterface $user + * @return Symfony\Component\Security\Core\User\User + */ + public function refreshUser(UserInterface $user) + { + if (!$user instanceof User) { + throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', get_class($user))); + } + return $this->loadUserByUsername($user->getUsername()); + } + + /*! + * @method supportsClass + * @public + * @param str $class + * @return bool + */ + public function supportsClass($class) { + return $class === User::class; + } + +}