/** * テーブルマイグレートを自動解決する * @param unknown $argDBO * @param unknown $argTable * @return boolean */ public static function resolve($argDBO, $argTblName, $argLastMigrationHash = NULL) { static $executed = array(); // 1プロセス内で同じテーブルに対してのマイグレーションを2度も処理しない if (FALSE === (isset($executed[$argTblName]) && TRUE === $executed[$argTblName])) { $firstMigration = TRUE; if (!isset(ORMapper::$modelHashs[$argTblName])) { // コンソールから強制マイグレーションされる時に恐らくココを通る $nowModel = ORMapper::getModel($argDBO, $argTblName); } // XXX ORMapperとMigrationManagerは循環しているのでいじる時は気をつけて! $modelHash = ORMapper::$modelHashs[$argTblName]; // modelハッシュがmigrationハッシュに含まれていないかどうか $migrationHash = $argLastMigrationHash; if (NULL === $migrationHash) { // 既に見つけているマイグレーションハッシュから定義を取得する $diff = self::_getDiff($argDBO, $argTblName); if (NULL !== self::$_lastMigrationHash) { $migrationHash = self::$_lastMigrationHash; } } debug('$migrationHash=' . $migrationHash); debug('$modelHash=' . $modelHash); // マイグレーションハッシュがある場合は if (NULL !== $migrationHash) { if (FALSE !== strpos($migrationHash, $modelHash)) { // このテーブルはマイグレーション済み $executed[$argTblName] = TRUE; // 現在のテーブル定義と最新のマイグレーションファイル上のテーブルハッシュに差分が無いので何もしない debug('exists migration! ' . $migrationHash); return TRUE; } // 最後に適用している該当テーブルに対してのマイグレーションクラスを読み込んでmodelハッシュを比較する $migrationFilePath = getAutoMigrationPath() . $argDBO->dbidentifykey . '.' . $migrationHash . '.migration.php'; if (TRUE === file_exists($migrationFilePath) && TRUE === is_file($migrationFilePath)) { // 既にテーブルはあるとココで断定 $firstMigration = FALSE; // 直前のマイグレーションクラスをインスタンス化 @(include_once $migrationFilePath); // モデルハッシュが変わっているかどうかを比較 if ($modelHash == $migrationHash::$migrationHash) { // このテーブルはマイグレーション済み $executed[$argTblName] = TRUE; // 現在のテーブル定義と最新のマイグレーションファイル上のテーブルハッシュに差分が無いので何もしない return TRUE; } } } // テーブル定義を取得 $tableDefs = ORMapper::getModelPropertyDefs($argDBO, $argTblName); $describeDef = $tableDefs['describeDef']; $migrationClassDef = PHP_EOL; $migrationClassDef .= PHP_EOL . PHP_TAB . 'public function __construct(){' . PHP_EOL . PHP_TAB . PHP_TAB . str_replace('; ', ';' . PHP_EOL . PHP_TAB . PHP_TAB, $describeDef) . 'return;' . PHP_EOL . PHP_TAB . '}' . PHP_EOL; if (TRUE === $firstMigration) { // create指示を生成 $migrationClassDef .= PHP_EOL . PHP_TAB . 'public function up($argDBO){' . PHP_EOL . PHP_TAB . PHP_TAB . 'return $this->create($argDBO);' . PHP_EOL . PHP_TAB . '}' . PHP_EOL; // drop指示を生成 $migrationClassDef .= PHP_EOL . PHP_TAB . 'public function down($argDBO){' . PHP_EOL . PHP_TAB . PHP_TAB . 'return $this->drop($argDBO);' . PHP_EOL . PHP_TAB . '}' . PHP_EOL; } else { // ALTERかDROP指示を生成 $upAlterDef = '$alter = array(); '; $downAlterDef = '$alter = array(); '; // 差分をフィールドを走査して特定する $lastModel = new $migrationHash(); $beforeDescribes = $lastModel->describes; $describes = array(); $beforeFieldKey = NULL; eval(str_replace('$this->', '$', $describeDef)); // 増えてる減ってるでループの起点を切り替え if (count($describes) >= count($beforeDescribes)) { // フィールドが増えている もしくは数は変わらない foreach ($describes as $feldKey => $propary) { // 最新のテーブル定義に合わせて $alter = NULL; if (!array_key_exists($feldKey, $beforeDescribes)) { // 増えてるフィールドを単純に増やす $alter = 'ADD'; $downAlterDef .= '$alter["' . $feldKey . '"] = array(); '; $downAlterDef .= '$alter["' . $feldKey . '"]["alter"] = "DROP"; '; } elseif (sha1(serialize($propary)) != sha1(serialize($beforeDescribes[$feldKey]))) { // ハッシュ値が違うので新しいフィールド情報でAlterする $alter = 'MODIFY'; // 元に戻すMODYFI $alterDefs = ORMapper::getModelPropertyDefs($argDBO, $argTblName, array($feldKey => $beforeDescribes[$feldKey])); $downAlterDef .= str_replace('$this->describes = array(); ', '', $alterDefs['describeDef']); $downAlterDef .= '$alter["' . $feldKey . '"]["alter"] = "' . $alter . '"; '; } if (NULL === $alter) { // 処理をスキップして次のループへ $beforeFieldKey = $feldKey; continue; } // up生成 $alterDefs = ORMapper::getModelPropertyDefs($argDBO, $argTblName, array($feldKey => $propary)); $upAlterDef .= str_replace('$this->describes = array(); ', '', $alterDefs['describeDef']); $upAlterDef .= '$alter["' . $feldKey . '"]["alter"] = "' . $alter . '"; '; if ('ADD' === $alter) { if (NULL === $beforeFieldKey) { // 先頭にフィールドが増えている $upAlterDef .= '$alter["' . $feldKey . '"]["first"] = TRUE;'; } else { // ADDする箇所の指定 $upAlterDef .= '$alter["' . $feldKey . '"]["after"] = "' . $beforeFieldKey . '";'; } } $beforeFieldKey = $feldKey; } } else { // フィールドが減っている // XXX upとdownがただ増えている時と逆なだけ foreach ($beforeDescribes as $feldKey => $propary) { // 前のテーブル定義に合わせて $alter = NULL; if (!array_key_exists($feldKey, $describes)) { // 減ってるフィールドを単純にARTER DROPする $alter = 'ADD'; $upAlterDef .= '$alter["' . $feldKey . '"] = array(); '; $upAlterDef .= '$alter["' . $feldKey . '"]["alter"] = "DROP"; '; } elseif (sha1(serialize($propary)) != sha1(serialize($describes[$feldKey]))) { // ハッシュ値が違うので新しいフィールド情報でAlterする $alter = 'MODIFY'; // 元に戻すMODYFI $alterDefs = ORMapper::getModelPropertyDefs($argDBO, $argTblName, array($feldKey => $describes[$feldKey])); $upAlterDef .= str_replace('$this->describes = array(); ', '', $alterDefs['describeDef']); $upAlterDef .= '$alter["' . $feldKey . '"]["alter"] = "' . $alter . '"; '; } if (NULL === $alter) { // 処理をスキップして次のループへ $beforeFieldKey = $feldKey; continue; } // down生成 $alterDefs = ORMapper::getModelPropertyDefs($argDBO, $argTblName, array($feldKey => $propary)); $downAlterDef .= str_replace('$this->describes = array(); ', '', $alterDefs['describeDef']); $downAlterDef .= '$alter["' . $feldKey . '"]["alter"] = "' . $alter . '"; '; if ('ADD' === $alter) { if (NULL === $beforeFieldKey) { // 先頭にフィールドが増えている $downAlterDef .= '$alter["' . $feldKey . '"]["first"] = TRUE;'; } else { // ADDする箇所の指定 $downAlterDef .= '$alter["' . $feldKey . '"]["after"] = "' . $beforeFieldKey . '";'; } } $beforeFieldKey = $feldKey; } } // alter指示を生成 $migrationClassDef .= PHP_EOL . PHP_TAB . 'public function up($argDBO){' . PHP_EOL . PHP_TAB . PHP_TAB . str_replace('$this->describes', '$alter', str_replace('; ', ';' . PHP_EOL . PHP_TAB . PHP_TAB, $upAlterDef)) . PHP_EOL . PHP_TAB . PHP_TAB . 'return $this->alter($argDBO, $alter);' . PHP_EOL . PHP_TAB . '}' . PHP_EOL; $migrationClassDef .= PHP_EOL . PHP_TAB . 'public function down($argDBO){' . PHP_EOL . PHP_TAB . PHP_TAB . str_replace('$this->describes', '$alter', str_replace('; ', ';' . PHP_EOL . PHP_TAB . PHP_TAB, $downAlterDef)) . PHP_EOL . PHP_TAB . PHP_TAB . 'return $this->alter($argDBO, $alter);' . PHP_EOL . PHP_TAB . '}' . PHP_EOL; } // 現在の定義でマイグレーションファイルを生成する $migrationClassName = self::_createMigrationClassName($argTblName) . '_' . $modelHash; $migrationClassDef = 'class ' . $migrationClassName . ' extends MigrationBase {' . PHP_EOL . PHP_EOL . PHP_TAB . 'public $tableName = "' . strtolower($argTblName) . '";' . PHP_EOL . PHP_EOL . PHP_TAB . 'public static $migrationHash = "' . $modelHash . '";' . $migrationClassDef . '}'; $path = getAutoMigrationPath() . $argDBO->dbidentifykey . '.' . $migrationClassName . '.migration.php'; @file_put_contents($path, '<?php' . PHP_EOL . PHP_EOL . $migrationClassDef . PHP_EOL . PHP_EOL . '?>'); @chmod($path, 0777); // 生成した場合は、生成環境のマイグレーションが最新で、適用済みと言う事になるので // マイグレーション済みファイルを生成し、新たにマイグレーション一覧に追記する @file_put_contents_e(getAutoMigrationPath() . $argDBO->dbidentifykey . '.all.migrations', $migrationClassName . PHP_EOL, FILE_APPEND); @file_put_contents_e(getAutoMigrationPath() . $argDBO->dbidentifykey . '.dispatched.migrations', $migrationClassName . PHP_EOL, FILE_APPEND); $executed[$argTblName] = TRUE; debug('migration! ' . $migrationClassName); } return TRUE; }
/** * 登録する * @param string DB接続情報 */ public static function registration($argID = NULL, $argPass = NULL, $argDSN = NULL) { if (FALSE === self::$_initialized) { self::_init($argDSN); } $id = $argID; $pass = $argPass; if (NULL === $id) { if (TRUE === class_exists('Flow', FALSE) && isset(Flow::$params) && isset(Flow::$params['post']) && TRUE === is_array(Flow::$params['post']) && isset(Flow::$params['post'][self::$authIDField])) { // Flowに格納されているPOSTパラメータを自動で使う $id = Flow::$params['post'][self::$authIDField]; } if (isset($_REQUEST) && isset($_REQUEST[self::$authIDField])) { // リクエストパラメータから直接受け取る $id = $_REQUEST[self::$authIDField]; } } if (NULL === $pass) { if (TRUE === class_exists('Flow', FALSE) && isset(Flow::$params) && isset(Flow::$params['post']) && TRUE === is_array(Flow::$params['post']) && isset(Flow::$params['post'][self::$authPassField])) { // Flowに格納されているPOSTパラメータを自動で使う $pass = Flow::$params['post'][self::$authPassField]; } if (isset($_REQUEST) && isset($_REQUEST[self::$authPassField])) { // リクエストパラメータから直接受け取る $pass = $_REQUEST[self::$authPassField]; } } $id = self::_resolveEncrypted($id, self::$authIDEncrypted); $pass = self::_resolveEncrypted($pass, self::$authPassEncrypted); $gmtDate = Utilities::date('Y-m-d H:i:s', NULL, NULL, 'GMT'); $query = '`' . self::$authIDField . '` = :' . self::$authIDField . ' AND `' . self::$authPassField . '` = ' . self::$authPassField . ' '; $binds = array(self::$authIDField => $id, self::$authPassField => $pass); $User = ORMapper::getModel(self::$_DBO, self::$authTable, $query, $binds); $User->{'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', self::$authIDField)))}($id); $User->{'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', self::$authPassField)))}($pass); $User->{'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', self::$authCreatedField)))}($gmtDate); $User->{'set' . str_replace(' ', '', ucwords(str_replace('_', ' ', self::$authModifiedField)))}($gmtDate); if (TRUE === $User->save()) { // ユーザーの登録は完了とみなし、コミットを行う! self::$_DBO->commit(); } return $User; }
protected function _getModel($argModel, $argIdentifierORQuery = NULL, $argBinds = NULL, $argDSN = NULL) { if (NULL !== $argIdentifierORQuery) { return ORMapper::getModel(self::_getDBO($argDSN), $argModel, $argIdentifierORQuery, $argBinds); } else { return ORMapper::getModel(self::_getDBO($argDSN), $argModel); } }
public static function clear() { if (FALSE === self::$_initialized) { // 自動セッションスタート self::_init(); } // 8バイト以下の$_COOKIE[self::$_tokenKeyName]はセットされていてもTOKENとして認めない if (isset($_COOKIE[self::$_tokenKeyName]) && strlen($_COOKIE[self::$_tokenKeyName]) > 8) { // Cookieが在る場合はCookieからトークンと固有識別子を初期化する $token = $_COOKIE[self::$_tokenKeyName]; // SESSIONレコードを走査 $binds = array(self::$_sessionPKeyName => $token); $Session = ORMapper::getModel(self::$_DBO, self::$_sessionTblName, '`' . self::$_sessionPKeyName . '` = :' . self::$_sessionPKeyName . ' limit 1', $binds); if (strlen($Session->{self::$_sessionPKeyName}) > 0) { // 該当レコードを削除 $Session->remove(); } // check無しの$identifierの特定 $identifier = self::_tokenToIdentifier($token, TRUE); if (FALSE !== $identifier && strlen($identifier) > 0) { // 該当のSessionDataも削除 parent::clear($identifier); } debug('cookie clear!'); // 二度処理しない為に削除する unset($_COOKIE[self::$_tokenKeyName]); setcookie(self::$_tokenKeyName, '', time() - 3600); } return TRUE; }
/** * identifierに紐づくセッションデータレコードをクリアする * @param string セッションデータのプライマリーキー * @param int 有効期限の直指定 * @param mixed DBDSN情報の直指定 */ public static function clear($argPKey = NULL, $argExpiredtime = NULL, $argDSN = NULL) { if (FALSE === self::$_initialized) { self::_init($argExpiredtime, $argDSN); } $binds = array(self::$_sessionDataPKeyName => $argPKey); $Session = ORMapper::getModel(self::$_DBO, self::$_sessionDataTblName, '`' . self::$_sessionDataPKeyName . '` = :' . self::$_sessionDataPKeyName . ' limit 1', $binds); $Session->remove(); }