/** * Set the model file of one module. If there's an extension file, merge it with the main model file. * * @param string $moduleName the module name * @static * @access public * @return string the model file */ public static function setModelFile($moduleName) { global $app; /* Set the main model file and extension and hook pathes and files. */ $mainModelFile = $app->getModulePath($moduleName) . 'model.php'; $modelExtPath = $app->getModuleExtPath($moduleName, 'model'); $modelHookPath = $modelExtPath . 'hook/'; $extFiles = helper::ls($modelExtPath, '.php'); $hookFiles = helper::ls($modelHookPath, '.php'); /* If no extension files and no hook files, return the main file directly. */ if (empty($extFiles) and empty($hookFiles)) { return $mainModelFile; } /* Else, judge whether needed update or not .*/ $needUpdate = false; $mergedModelFile = $app->getTmpRoot() . 'model' . $app->getPathFix() . $moduleName . '.php'; $lastTime = file_exists($mergedModelFile) ? filemtime($mergedModelFile) : 0; while (!$needUpdate) { foreach ($extFiles as $extFile) { if (filemtime($extFile) > $lastTime) { break 2; } } foreach ($hookFiles as $hookFile) { if (filemtime($hookFile) > $lastTime) { break 2; } } if (is_dir($modelExtPath) and filemtime($modelExtPath) > $lastTime) { break; } if (is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) { break; } if (filemtime($mainModelFile) > $lastTime) { break; } return $mergedModelFile; } /* Update the cache file. */ $modelClass = $moduleName . 'Model'; $extModelClass = 'ext' . $modelClass; $extTmpModelClass = 'tmpExt' . $modelClass; $modelLines = "<?php\n"; $modelLines .= "helper::import('{$mainModelFile}');\n"; $modelLines .= "class {$extTmpModelClass} extends {$modelClass} \n{\n"; /* Cycle all the extension files. */ foreach ($extFiles as $extFile) { $extLines = self::removeTagsOfPHP($extFile); $modelLines .= $extLines . "\n"; } /* Create the merged model file and import it. */ $replaceMark = '//**//'; // This mark is for replacing code using. $modelLines .= "{$replaceMark}\n}"; if (!@file_put_contents($mergedModelFile, $modelLines)) { die("ERROR: {$mergedModelFile} not writable, please make sur the " . dirname($mergedModelFile) . ' directory exists and writable'); } if (!class_exists($extTmpModelClass)) { include $mergedModelFile; } /* Get hook codes need to merge. */ $hookCodes = array(); foreach ($hookFiles as $hookFile) { $fileName = baseName($hookFile); list($method) = explode('.', $fileName); $hookCodes[$method][] = self::removeTagsOfPHP($hookFile); } /* Cycle the hook methods and merge hook codes. */ $hookedMethods = array_keys($hookCodes); $mainModelCodes = file($mainModelFile); $mergedModelCodes = file($mergedModelFile); foreach ($hookedMethods as $method) { /* Reflection the hooked method to get it's defined position. */ $methodRelfection = new reflectionMethod($extTmpModelClass, $method); $definedFile = $methodRelfection->getFileName(); $startLine = $methodRelfection->getStartLine() . ' '; $endLine = $methodRelfection->getEndLine() . ' '; /* Merge hook codes. */ $oldCodes = $definedFile == $mergedModelFile ? $mergedModelCodes : $mainModelCodes; $oldCodes = join("", array_slice($oldCodes, $startLine - 1, $endLine - $startLine + 1)); $openBrace = strpos($oldCodes, '{'); $newCodes = substr($oldCodes, 0, $openBrace + 1) . "\n" . join("\n", $hookCodes[$method]) . substr($oldCodes, $openBrace + 1); /* Replace it. */ if ($definedFile == $mergedModelFile) { $modelLines = str_replace($oldCodes, $newCodes, $modelLines); } else { $modelLines = str_replace($replaceMark, $newCodes . "\n{$replaceMark}", $modelLines); } } /* Save it. */ $modelLines = str_replace($extTmpModelClass, $extModelClass, $modelLines); file_put_contents($mergedModelFile, $modelLines); return $mergedModelFile; }
/** * Set the model file of one module. If there's an extension file, merge it with the main model file. * * @param string $moduleName the module name * @static * @access public * @return string the model file */ public static function setModelFile($moduleName) { global $app; /* Set the main model file and extension and hook pathes and files. */ $mainModelFile = $app->getModulePath($moduleName) . 'model.php'; $modelExtPath = $app->getModuleExtPath($moduleName, 'model'); $modelHookPath = $modelExtPath . 'hook/'; $extFiles = helper::ls($modelExtPath, '.php'); $hookFiles = helper::ls($modelHookPath, '.php'); /* If no extension files and no hook files, return the main file directly. */ if (empty($extFiles) and empty($hookFiles)) { return $mainModelFile; } /* Else, judge whether needed update or not .*/ $needUpdate = false; $mergedModelFile = $app->getTmpRoot() . 'model' . $app->getPathFix() . $moduleName . '.php'; $lastTime = file_exists($mergedModelFile) ? filemtime($mergedModelFile) : 0; while (!$needUpdate) { foreach ($extFiles as $extFile) { if (filemtime($extFile) > $lastTime) { break 2; } } foreach ($hookFiles as $hookFile) { if (filemtime($hookFile) > $lastTime) { break 2; } } if (is_dir($modelExtPath) and filemtime($modelExtPath) > $lastTime) { break; } if (is_dir($modelHookPath) and filemtime($modelHookPath) > $lastTime) { break; } if (filemtime($mainModelFile) > $lastTime) { break; } return $mergedModelFile; } /* If loaded zend opcache module, turn off cache when create tmp model file to avoid the conflics. */ if (extension_loaded('Zend OPcache')) { ini_set('opcache.enable', 0); } /* Update the cache file. */ $modelClass = $moduleName . 'Model'; $extModelClass = 'ext' . $modelClass; $extTmpModelClass = 'tmpExt' . $modelClass; $modelLines = "<?php\n"; $modelLines .= "helper::import('{$mainModelFile}');\n"; $modelLines .= "class {$extTmpModelClass} extends {$modelClass} \n{\n"; /* Cycle all the extension files. */ foreach ($extFiles as $extFile) { $extLines = self::removeTagsOfPHP($extFile); $modelLines .= $extLines . "\n"; } /* Create the merged model file and import it. */ $replaceMark = '//**//'; // This mark is for replacing code using. $modelLines .= "{$replaceMark}\n}"; /* Unset conflic function for model. */ preg_match_all('/.* function\\s+(\\w+)\\s*\\(.*\\)[^\\{]*\\{/Ui', $modelLines, $functions); $functions = $functions[1]; $conflics = array_count_values($functions); foreach ($conflics as $functionName => $count) { if ($count <= 1) { unset($conflics[$functionName]); } } if ($conflics) { $modelLines = explode("\n", $modelLines); $startDel = false; foreach ($modelLines as $line => $code) { if ($startDel and preg_match('/.* function\\s+(\\w+)\\s*\\(.*\\)/Ui', $code)) { $startDel = false; } if ($startDel) { unset($modelLines[$line]); } else { foreach ($conflics as $functionName => $count) { if ($count <= 1) { continue; } if (preg_match('/.* function\\s+' . $functionName . '\\s*\\(.*\\)/Ui', $code)) { $conflics[$functionName] = $count - 1; $startDel = true; unset($modelLines[$line]); } } } } $modelLines = join("\n", $modelLines); } $tmpMergedModelFile = $app->getTmpRoot() . 'model' . $app->getPathFix() . 'tmp.' . $moduleName . '.php'; if (!@file_put_contents($tmpMergedModelFile, $modelLines)) { die("ERROR: {$tmpMergedModelFile} not writable, please make sure the " . dirname($tmpMergedModelFile) . ' directory exists and writable'); } if (!class_exists($extTmpModelClass)) { include $tmpMergedModelFile; } /* Get hook codes need to merge. */ $hookCodes = array(); foreach ($hookFiles as $hookFile) { $fileName = baseName($hookFile); list($method) = explode('.', $fileName); $hookCodes[$method][] = self::removeTagsOfPHP($hookFile); } /* Cycle the hook methods and merge hook codes. */ $hookedMethods = array_keys($hookCodes); $mainModelCodes = file($mainModelFile); $mergedModelCodes = file($tmpMergedModelFile); foreach ($hookedMethods as $method) { /* Reflection the hooked method to get it's defined position. */ $methodRelfection = new reflectionMethod($extTmpModelClass, $method); $definedFile = $methodRelfection->getFileName(); $startLine = $methodRelfection->getStartLine() . ' '; $endLine = $methodRelfection->getEndLine() . ' '; /* Merge hook codes. */ $oldCodes = $definedFile == $tmpMergedModelFile ? $mergedModelCodes : $mainModelCodes; $oldCodes = join("", array_slice($oldCodes, $startLine - 1, $endLine - $startLine + 1)); $openBrace = strpos($oldCodes, '{'); $newCodes = substr($oldCodes, 0, $openBrace + 1) . "\n" . join("\n", $hookCodes[$method]) . substr($oldCodes, $openBrace + 1); /* Replace it. */ if ($definedFile == $tmpMergedModelFile) { $modelLines = str_replace($oldCodes, $newCodes, $modelLines); } else { $modelLines = str_replace($replaceMark, $newCodes . "\n{$replaceMark}", $modelLines); } } unlink($tmpMergedModelFile); /* Save it. */ $modelLines = str_replace($extTmpModelClass, $extModelClass, $modelLines); file_put_contents($mergedModelFile, $modelLines); return $mergedModelFile; }
protected function getDeclaringClass(\reflectionMethod $method) { $declaringClass = $method->getDeclaringClass(); $traits = $this->adapter->method_exists($declaringClass, 'getTraits') === false ? array() : $declaringClass->getTraits(); if (sizeof($traits) > 0) { $methodFileName = $method->getFileName(); if ($methodFileName !== $declaringClass->getFileName() || $method->getStartLine() < $declaringClass->getStartLine() || $method->getEndLine() > $declaringClass->getEndLine()) { if (sizeof($traits) > 0) { $methodName = $method->getName(); foreach ($traits as $trait) { if ($methodFileName === $trait->getFileName() && $trait->hasMethod($methodName) === true) { return $trait; } } } } } return $declaringClass; }