/** * configの読み込みとconfigureクラスの定義を実行する */ function loadConfig($argConfigPath) { // 自動ジェネレートフラグの取得 $autoGenerateFlag = getAutoGenerateEnabled(); static $autoMigrationFlag = NULL; static $localFlag = NULL; static $devFlag = NULL; static $testFlag = NULL; static $stagingFlag = NULL; static $debugFlag = NULL; static $errorReportFlag = NULL; static $regenerateFlag = NULL; if (NULL === $errorReportFlag) { // 自動マイグレート設定フラグのセット $autoMigrationFlag = getAutoMigrationEnabled(); // ローカル環境フラグのセット $localFlag = getLocalEnabled(); // 開発環境フラグのセット $devFlag = getDevelopmentEnabled(); // テスト環境(テスト用凍結環境)フラグのセット $testFlag = getTestEnabled(); // ステージング環境フラグのセット $stagingFlag = getStagingEnabled(); // デバッグモードフラグのセット $debugFlag = getDebugEnabled(); // エラーレポートフラグのセット $errorReportFlag = getErrorReportEnabled(); } if (TRUE === $autoGenerateFlag) { if (is_file($argConfigPath)) { // フラグメントキャッシュの更新が有れば、コンフィグファイルを強制再読み込みする為のチェック if (NULL === $regenerateFlag) { $flagcacheFileName = getAutoGeneratedPath() . 'flagcache.php'; if (file_exists($flagcacheFileName)) { require_once $flagcacheFileName; if (TRUE !== (TRUE === isset($flagchaces['autoMigrationFlag']) && (int) $autoMigrationFlag == $flagchaces['autoMigrationFlag'])) { $regenerateFlag = TRUE; } if (!isset($flagchaces['localFlag']) || (int) $localFlag != $flagchaces['localFlag']) { $regenerateFlag = TRUE; } if (!isset($flagchaces['devFlag']) || (int) $devFlag != $flagchaces['devFlag']) { $regenerateFlag = TRUE; } if (!isset($flagchaces['testFlag']) || (int) $testFlag != $flagchaces['testFlag']) { $regenerateFlag = TRUE; } if (!isset($flagchaces['stagingFlag']) || (int) $stagingFlag != $flagchaces['stagingFlag']) { $regenerateFlag = TRUE; } if (!isset($flagchaces['debugFlag']) || (int) $debugFlag != $flagchaces['debugFlag']) { $regenerateFlag = TRUE; } if (!isset($flagchaces['errorReportFlag']) || (int) $errorReportFlag != $flagchaces['errorReportFlag']) { $regenerateFlag = TRUE; } } else { $regenerateFlag = TRUE; } if (TRUE === $regenerateFlag) { $flagchaceBody = '$flagchaces = array(\'autoMigrationFlag\'=>' . (int) $autoMigrationFlag . ', \'localFlag\'=>' . (int) $localFlag . ', \'devFlag\'=>' . (int) $devFlag . ', \'testFlag\'=>' . (int) $testFlag . ', \'stagingFlag\'=>' . (int) $stagingFlag . ', \'debugFlag\'=>' . (int) $debugFlag . ', \'errorReportFlag\'=>' . (int) $errorReportFlag . ');'; // フラグメントキャッシュを更新 file_put_contents($flagcacheFileName, '<?php' . PHP_EOL . $flagchaceBody . PHP_EOL . '?>'); @chmod($flagcacheFileName, 0777); } } if (TRUE !== $regenerateFlag) { $configFileName = basename($argConfigPath); $generatedConfigFileName = getAutoGeneratedPath() . $configFileName . '.generated.php'; if (file_exists($generatedConfigFileName) && filemtime($generatedConfigFileName) >= filemtime($argConfigPath)) { // 静的ファイル化されたコンフィグクラスファイルを読み込んで終了 // fatal errorがいいのでrequireする require_once $generatedConfigFileName; // リプレースは不要 $regenerateFlag = FALSE; return TRUE; } } } } if (!is_file($argConfigPath)) { return FALSE; } // configureの初期化 $configs = array(); $configure = simplexml_load_file($argConfigPath, NULL, LIBXML_NOCDATA); // 環境フラグをセット if (!class_exists('Configure', FALSE)) { $configure->addChild('AUTO_GENERATE_ENABLED', $autoGenerateFlag); $configure->addChild('AUTO_MIGRATE_ENABLED', $autoMigrationFlag); $configure->addChild('LOCAL_ENABLED', $localFlag); $configure->addChild('DEV_ENABLED', $devFlag); $configure->addChild('TEST_ENABLED', $testFlag); $configure->addChild('STAGING_ENABLED', $stagingFlag); $configure->addChild('DEBUG_ENABLED', $debugFlag); $configure->addChild('ERROR_REPORT_ENABLED', $errorReportFlag); } foreach (get_object_vars($configure) as $key => $val) { if ('comment' != $key) { if (count($configure->{$key}->children()) > 0) { if (!isset($configs[$key . 'Configure'])) { $configs[$key . 'Configure'] = ''; } foreach (get_object_vars($val) as $key2 => $val2) { $evalFlag = FALSE; if (count($val2) > 1) { $skip = TRUE; for ($attrCnt = 0; count($val2) > $attrCnt; $attrCnt++) { if (isset($configure->{$key}->{$key2}[$attrCnt]->attributes()->stage)) { $stage = $configure->{$key}->{$key2}[$attrCnt]->attributes()->stage; if ('local' == $stage && TRUE === $localFlag) { $skip = FALSE; break; } elseif ('dev' == $stage && TRUE === $devFlag) { $skip = FALSE; break; } elseif ('test' == $stage && TRUE === $testFlag) { $skip = FALSE; break; } elseif ('staging' == $stage && TRUE === $stagingFlag) { $skip = FALSE; break; } } else { $defAttrCnt = $attrCnt; } } if (TRUE === $skip) { $attrCnt = $defAttrCnt; } $val2 = $val2[$attrCnt]; if (isset($configure->{$key}->{$key2}[$attrCnt]->attributes()->code)) { $evalFlag = TRUE; } } elseif (isset($configure->{$key}->{$key2}) && isset($configure->{$key}->{$key2}->attributes()->code)) { $evalFlag = TRUE; } $val2 = trim($val2); $matches = NULL; if (preg_match_all('/\\%(.+)\\%/', $val2, $matches) > 0) { for ($matchCnt = 0; count($matches[0]) > $matchCnt; $matchCnt++) { $matchKey = $matches[0][$matchCnt]; $matchStr = $matches[1][$matchCnt]; $val2 = substr_replace($val2, $configure->{$key}->{$matchStr}, strpos($val2, $matchKey), strlen($matchKey)); } } if (TRUE === $evalFlag) { if (FALSE !== strpos($val2, '__FILE__')) { $val2 = str_replace('__FILE__', '\'' . realpath($argConfigPath) . '\'', $val2); } @eval('$val2 = ' . $val2 . ';'); //$configure->{$key}->{$key2} = $val2; $configs[$key . 'Configure'] .= PHP_TAB . 'const ' . $key2 . ' = \'' . $val2 . '\';' . PHP_EOL; } else { if (strlen($val2) == 0) { $configs[$key . 'Configure'] .= PHP_TAB . 'const ' . $key2 . ' = \'\';' . PHP_EOL; } elseif ('TRUE' == strtoupper($val2) || 'FALSE' == strtoupper($val2) || 'NULL' == strtoupper($val2) || is_numeric($val2)) { $configs[$key . 'Configure'] .= PHP_TAB . 'const ' . $key2 . ' = ' . $val2 . ';' . PHP_EOL; } else { $configs[$key . 'Configure'] .= PHP_TAB . 'const ' . $key2 . ' = \'' . addslashes($val2) . '\';' . PHP_EOL; } } } } else { $evalFlag = FALSE; if (count($val) > 1) { $skip = TRUE; for ($attrCnt = 0; count($val) > $attrCnt; $attrCnt++) { if (isset($configure->{$key}[$attrCnt]->attributes()->stage)) { $stage = $configure->{$key}[$attrCnt]->attributes()->stage; if ('local' == $stage && TRUE === $localFlag) { $skip = FALSE; break; } elseif ('dev' == $stage && TRUE === $devFlag) { $skip = FALSE; break; } elseif ('test' == $stage && TRUE === $testFlag) { $skip = FALSE; break; } elseif ('staging' == $stage && TRUE === $stagingFlag) { $skip = FALSE; break; } } else { $defAttr = $attrCnt; } } if (TRUE === $skip) { $attrCnt = $defAttr; } $val = $val[$attrCnt]; if (isset($configure->{$key}[$attrCnt]->attributes()->code)) { $evalFlag = TRUE; } } elseif (isset($configure->{$key}->attributes()->code)) { $evalFlag = TRUE; } $val = trim($val); $matches = NULL; if (preg_match_all('/\\%(.+)\\%/', $val, $matches) > 0) { for ($matchCnt = 0; count($matches[0]) > $matchCnt; $matchCnt++) { $matchKey = $matches[0][$matchCnt]; $matchStr = $matches[1][$matchCnt]; $val = substr_replace($val, $configure->{$matchStr}, strpos($val, $matchKey), strlen($matchKey)); } } if (TRUE === $evalFlag) { if (FALSE !== strpos($val, '__FILE__')) { $val = str_replace('__FILE__', '\'' . realpath($argConfigPath) . '\'', $val); } eval('$val = ' . $val . ';'); if (!isset($configs['Configure'])) { $configs['Configure'] = ''; } $configs['Configure'] .= PHP_TAB . 'const ' . $key . ' = \'' . $val . '\';' . PHP_EOL; } else { if (!isset($configs['Configure'])) { $configs['Configure'] = ''; } if (strlen($val) == 0) { $configs['Configure'] .= PHP_TAB . 'const ' . $key . ' = \'\';' . PHP_EOL; } elseif ('TRUE' == strtoupper($val) || 'FALSE' == strtoupper($val) || 'NULL' == strtoupper($val) || is_numeric($val)) { $configs['Configure'] .= PHP_TAB . 'const ' . $key . ' = ' . $val . ';' . PHP_EOL; } else { // XXX ココ危険!!!addslashesしないと行けないシチュエーションが出てくるかも $configs['Configure'] .= PHP_TAB . 'const ' . $key . ' = \'' . addslashes($val) . '\';' . PHP_EOL; } } } } } static $baseConfigureClassDefine = NULL; if (NULL === $baseConfigureClassDefine) { /*------------------------------ Configureクラス定義のスケルトン ココから ------------------------------*/ $baseConfigureClassDefine = <<<_CLASSDEF_ class %class% { \t%consts% \tprivate static function _search(\$argVal,\$argKey,\$argHints){ \t\tif(preg_match('/'.\$argHints['hint'].'/',\$argKey)){ \t\t\t\$argHints['data'][\$argKey] = \$argVal; \t\t} \t} \tpublic static function constant(\$argHint,\$argSearchFlag = FALSE){ \t\tstatic \$myConsts = NULL; \t\tif(FALSE !== \$argSearchFlag){ \t\t\tif(NULL === \$myConsts){ \t\t\t\t\$ref = new ReflectionClass(__CLASS__); \t\t\t\t\$myConsts = \$ref->getConstants(); \t\t\t} \t\t\t\$tmpArr = array(); \t\t\tforeach(\$myConsts as \$key => \$val){ \t\t\t\tif(preg_match('/'.\$argHint.'/',\$key)){ \t\t\t\t\t\$tmpArr[\$key] = \$val; \t\t\t\t} \t\t\t} \t\t\tif(count(\$tmpArr)>0){ \t\t\t\treturn \$tmpArr; \t\t\t} \t\t} \t\telseif(TRUE === defined('self::'.\$argHint)){ \t\t\treturn constant('self::'.\$argHint); \t\t} \t\treturn NULL; \t} } \$paths = %class%::constant(".+_PATH\$", TRUE); foreach(\$paths as \$key => \$val){ \tset_include_path(get_include_path().PATH_SEPARATOR.\$val); } _CLASSDEF_; /*------------------------------ Configureクラス定義のスケルトン ココまで ------------------------------*/ } // Configureクラスを宣言する $configGeneratClassDefine = NULL; foreach ($configs as $key => $val) { $configClassDefine = $baseConfigureClassDefine; if ('Configure' !== $key) { $configClassDefine .= "\r\n/*requireに成功しているので、initFrameworkでコンフィグを追加する*/\r\n_initFramework('%class%');"; } $configClassDefine = str_replace('%class%', ucwords($key), $configClassDefine); $configClassDefine = str_replace('%consts%', substr($val, 1), $configClassDefine); if (TRUE === $autoGenerateFlag) { $configGeneratClassDefine .= $configClassDefine; } else { eval($configClassDefine); } } // ジェネレート処理 if (TRUE === $autoGenerateFlag) { $configFileName = basename($argConfigPath); $generatedConfigFileName = getAutoGeneratedPath() . $configFileName . '.generated.php'; // タブ文字削除 $configGeneratClassDefine = str_replace(PHP_TAB, '', $configGeneratClassDefine); // 改行文字削除 $configGeneratClassDefine = str_replace(array(PHP_CR, PHP_LF), '', $configGeneratClassDefine); file_put_contents($generatedConfigFileName, '<?php' . PHP_EOL . $configGeneratClassDefine . PHP_EOL . '?>'); @chmod($generatedConfigFileName, 0777); // 静的ファイル化されたコンフィグクラスファイルを読み込む require_once $generatedConfigFileName; } // インクルードパスの追加処理 foreach ($configs as $key => $val) { $ConfigClassName = ucwords($key); $paths = $ConfigClassName::constant(".+_PATH\$", TRUE); foreach ($paths as $key => $val) { set_include_path(get_include_path() . PATH_SEPARATOR . $val); } } return TRUE; }
/** * 定義情報をチェックする * @param string XMLファイルのパス文字列 or XML文字列 */ public static function generate($argTarget, $argSection, $argBasePathTarget = '') { $filepathUsed = FALSE; $targetXML = $argTarget; if (1024 >= strlen($argTarget) && TRUE === file_exists_ip($argTarget)) { // ファイルパス指定の場合はファイルの中身を文字列として一旦取得 $filepathUsed = TRUE; $targetXML = file_get_contents($argTarget); } // クラス名を確定する $className = $argSection; if (TRUE === $filepathUsed) { // オートジェネレートフラグの取得(フレームワークのコアから貰う) $autoGenerateFlag = getAutoGenerateEnabled(); if (TRUE === $autoGenerateFlag) { $generatedClassPath = self::_getAutogenerateFilePath($argTarget); // unlinkされたか if (FALSE === resolveUnlinkAutoGeneratedFile($generatedClassPath)) { // クラス名を返して終了 return $className; } } } // XML文字列を、XMLオブジェクト化 libxml_use_internal_errors(TRUE); $FlowXML = simplexml_load_string($targetXML); if (FALSE === $FlowXML) { throw new LibXMLException(libxml_get_errors()); } // FlowXMLとして正しいかどうか if (TRUE === self::validate($FlowXML)) { // $argSectionがIndex_authedだったとして、index-authedに変換される //$targetSection = str_replace('_', '-', ucfirst($argSection)); // FlowXMLに基いてコントローラクラスを自動生成する $classDef = ''; foreach ($FlowXML->children() as $firstNode) { // firstNodeのid属性から暮らす名を決める // idがindex-authedだったとして、Index_authedに変換される $tmpAttr = $firstNode->attributes(); $sectionClassName = str_replace('-', '_', ucfirst($tmpAttr['id'])); // 上位クラスは暫定でWebコントローラと言う事にする $extends = ' extends WebFlowControllerBase'; // 上位クラスが指定されているかどうか if (isset($tmpAttr['extends']) && strlen($tmpAttr['extends']) > 0) { // そのまま採用 $extends = ' extends ' . $tmpAttr['extends']; } elseif (isset($tmpAttr['type']) && strlen($tmpAttr['type']) > 0) { $typeStr = $tmpAttr['type']; // XXX $typeStrはSimpleXMLElementなので===の完全一致では動作しない! if ('web' == $typeStr) { $extends = ' extends WebFlowControllerBase'; } elseif ('api' == $typeStr) { $extends = ' extends APIControllerBase'; } elseif ('image' == $typeStr) { $extends = ' extends ImageControllerBase'; } } $methods = array(); // メソッド定義 foreach ($firstNode->children() as $methodNode) { // 2次元目はメソッド定義 $methodName = $methodNode->getName(); // constructとdestructだけをマジックメソッドのマップとしてサポートする if ('construct' == $methodName || 'destruct' == $methodName) { $methodName = '__' . $methodName; } $method = PHP_TAB . 'function ' . $methodName . '(%s){' . PHP_EOL . '%s' . PHP_EOL . PHP_TAB . PHP_TAB . 'return TRUE;' . PHP_EOL . PHP_TAB . '}' . PHP_EOL; $methodArg = ''; $methodArgs = $methodNode->attributes(); if (count($methodArgs) > 0) { $methodArg = array(); foreach ($methodArgs as $key => $val) { $arg = ''; $arg .= '$' . $key . ' = ' . self::_resolveValue($val); $methodArg[] = $arg; } $methodArg = implode(', ', $methodArg); } // 3次元目は以降はネスト構造のソースコード定義 $code = ''; if (isset($extends) && strlen($extends) > 0 && ' extends WebFlowControllerBase' == $extends) { // WebFlowBaseのinitをメソッドの頭で必ず呼ぶ $code .= PHP_TAB . PHP_TAB . '$autoValidated = parent::_initWebFlow();' . PHP_EOL; } foreach ($methodNode->children() as $codeNode) { $code .= self::_generateCode($codeNode, $argBasePathTarget); } $method = sprintf($method, $methodArg, $code); $methods[] = $method; } // クラス定義つなぎ合わせ $classDef .= PHP_EOL . 'class ' . $sectionClassName . $extends . PHP_EOL; $classDef .= '{' . PHP_EOL . PHP_EOL; $classDef .= PHP_TAB . 'public $section=\'' . basename($argSection) . '\';' . PHP_EOL; $classDef .= PHP_TAB . 'public $target=\'' . $argBasePathTarget . '\';' . PHP_EOL . PHP_EOL; for ($methodIdx = 0; count($methods) > $methodIdx; $methodIdx++) { $classDef .= $methods[$methodIdx]; } $classDef .= '}' . PHP_EOL; } // オートジェネレートチェック if (TRUE === $filepathUsed && TRUE === $autoGenerateFlag) { // 空でジェネレートファイルを生成 @file_put_contents($generatedClassPath, ''); // ジェネレート generateClassCache($generatedClassPath, $argTarget, $classDef, $className); // 静的ファイル化されたクラスファイルを読み込んで終了 // fatal errorがいいのでrequireする //require_once $generatedClassPath; } // オートジェネレートが有効だろうが無効だろうがココまで来たらクラス定義の実体化 eval($classDef); return $className; } return FALSE; }