00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 class Mage_Compiler_Model_Process
00036 {
00037 protected $_compileDir = null;
00038 protected $_includeDir = null;
00039 protected $_statDir = null;
00040 protected $_compileConfig = null;
00041 protected $_includePaths = array();
00042 protected $_processedClasses= array();
00043
00044 public function __construct($options=array())
00045 {
00046 if (isset($options['compile_dir'])) {
00047 $this->_compileDir = $options['compile_dir'];
00048 } else {
00049 $this->_compileDir = Mage::getBaseDir() . DS . 'includes';
00050 }
00051 $this->_includeDir = $this->_compileDir . DS . 'src';
00052 $this->_statDir = $this->_compileDir . DS . 'stat';
00053 }
00054
00055
00056
00057
00058
00059
00060 public function getCompileConfig()
00061 {
00062 if ($this->_compileConfig === null) {
00063 $this->_compileConfig = Mage::getConfig()->loadModulesConfiguration('compilation.xml');
00064 }
00065 return $this->_compileConfig;
00066 }
00067
00068
00069
00070
00071
00072
00073 protected function _getIncludePaths()
00074 {
00075 if (empty($this->_includePaths)) {
00076 $originalPath = Mage::registry('original_include_path');
00077 $path = str_replace($originalPath, '', get_include_path());
00078 $this->_includePaths = explode(PS, $path);
00079 foreach ($this->_includePaths as $index => $path) {
00080 if (empty($path)) {
00081 unset($this->_includePaths[$index]);
00082 }
00083 }
00084 }
00085 return $this->_includePaths;
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095 protected function _copy($source, $target, $firstIteration = true)
00096 {
00097 if (is_dir($source)) {
00098 $dir = dir($source);
00099 while (false !== ($file = $dir->read())) {
00100 if (($file[0] == '.')) {
00101 continue;
00102 }
00103 $sourceFile = $source . DS . $file;
00104 if ($file == 'controllers') {
00105 continue;
00106 }
00107
00108 if ($firstIteration) {
00109 $targetFile = $target . DS . $file;
00110 } else {
00111 $targetFile = $target . '_' . $file;
00112 }
00113 $this->_copy($sourceFile, $targetFile, false);
00114 }
00115 } else {
00116 if (strpos(str_replace($this->_includeDir, '', $target), '-')
00117 || !in_array(substr($source, strlen($source)-4, 4), array('.php'))) {
00118 return $this;
00119 }
00120 copy($source, $target);
00121 }
00122 return $this;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131 protected function _copyZendLocaleData($destDir)
00132 {
00133 $source = Mage::getBaseDir('lib').DS.'Zend'.DS.'Locale'.DS.'Data';
00134 $dir = dir($source);
00135 while (false !== ($file = $dir->read())) {
00136 if (($file[0] == '.')) {
00137 continue;
00138 }
00139 $sourceFile = $source . DS . $file;
00140 $targetFile = $destDir . DS . $file;
00141 copy($sourceFile, $targetFile);
00142 }
00143 return $this;
00144 }
00145
00146
00147
00148
00149
00150
00151
00152 protected function _mkdir($dir)
00153 {
00154 if (!is_dir($dir)) {
00155 mkdir($dir);
00156 @chmod($dir, 0777);
00157 }
00158 return $dir;
00159 }
00160
00161
00162
00163
00164
00165
00166 protected function _collectFiles()
00167 {
00168 $paths = $this->_getIncludePaths();
00169 $paths = array_reverse($paths);
00170 $destDir= $this->_includeDir;
00171
00172 $this->_mkdir($destDir);
00173 foreach ($paths as $path) {
00174 $this->_copy($path, $destDir);
00175 }
00176
00177 $destDir.= DS.'Data';
00178 $this->_mkdir($destDir);
00179 $this->_copyZendLocaleData($destDir);
00180 return $this;
00181 }
00182
00183 public function getCollectedFilesCount()
00184 {
00185 return count(glob($this->_includeDir.DS.'*'));
00186 }
00187
00188 public function getCompiledFilesCount()
00189 {
00190 return count(glob($this->_includeDir.DS.Varien_Autoload::SCOPE_FILE_PREFIX.'*'));
00191 }
00192
00193 public function getCompileClassList()
00194 {
00195 $arrFiles = array();
00196 $statDir = $this->_statDir;
00197 $statFiles= array();
00198 if (is_dir($statDir)) {
00199 $dir = dir($statDir);
00200 while (false !== ($file = $dir->read())) {
00201 if (($file[0] == '.')) {
00202 continue;
00203 }
00204 $statFiles[str_replace('.csv', '', $file)] = $this->_statDir.DS.$file;
00205 }
00206 }
00207
00208 foreach ($this->getCompileConfig()->getNode('includes')->children() as $code => $config) {
00209 $classes = $config->asArray();
00210 if (is_array($classes)) {
00211 $arrFiles[$code] = array_keys($classes);
00212 } else {
00213 $arrFiles[$code] = array();
00214 }
00215
00216 $statClasses = array();
00217 if (isset($statFiles[$code])) {
00218 $statClasses = explode("\n", file_get_contents($statFiles[$code]));
00219 $popularStatClasses = array();
00220 foreach ($statClasses as $index => $classInfo) {
00221 $classInfo = explode(':', $classInfo);
00222 $popularStatClasses[$classInfo[1]][] = $classInfo[0];
00223 }
00224 ksort($popularStatClasses);
00225 $statClasses = array_pop($popularStatClasses);
00226 unset($statFiles[$code]);
00227 }
00228 $arrFiles[$code] = array_merge($arrFiles[$code], $statClasses);
00229 $arrFiles[$code] = array_unique($arrFiles[$code]);
00230 sort($arrFiles[$code]);
00231 }
00232
00233 foreach($statFiles as $code => $file) {
00234 $classes = explode("\n", file_get_contents($file));
00235 $popularStatClasses = array();
00236 foreach ($classes as $index => $classInfo) {
00237 $classInfo = explode(':', $classInfo);
00238 $popularStatClasses[$classInfo[1]][] = $classInfo[0];
00239 }
00240 ksort($popularStatClasses);
00241 $arrFiles[$code] = array_pop($popularStatClasses);
00242 }
00243 foreach ($arrFiles as $scope=>$classes) {
00244 if ($scope != 'default') {
00245 foreach ($classes as $index => $class) {
00246 if (in_array($class, $arrFiles['default'])) {
00247 unset($arrFiles[$scope][$index]);
00248 }
00249 }
00250 }
00251 }
00252 return $arrFiles;
00253 }
00254
00255
00256
00257
00258
00259
00260 protected function _compileFiles()
00261 {
00262 $classesInfo = $this->getCompileClassList();
00263
00264 foreach ($classesInfo as $code => $classes) {
00265 $classesSorce = $this->_getClassesSourceCode($classes, $code);
00266 file_put_contents($this->_includeDir.DS.Varien_Autoload::SCOPE_FILE_PREFIX.$code.'.php', $classesSorce);
00267 }
00268 return $this;
00269 }
00270
00271 protected function _getClassesSourceCode($classes, $scope)
00272 {
00273 $sortedClasses = array();
00274 foreach ($classes as $className) {
00275 $implements = array_reverse(class_implements($className));
00276 foreach ($implements as $class) {
00277 if (!in_array($class, $sortedClasses) && !in_array($class, $this->_processedClasses) && strstr($class, '_')) {
00278 $sortedClasses[] = $class;
00279 if ($scope == 'default') {
00280 $this->_processedClasses[] = $class;
00281 }
00282 }
00283 }
00284 $extends = array_reverse(class_parents($className));
00285 foreach ($extends as $class) {
00286 if (!in_array($class, $sortedClasses) && !in_array($class, $this->_processedClasses) && strstr($class, '_')) {
00287 $sortedClasses[] = $class;
00288 if ($scope == 'default') {
00289 $this->_processedClasses[] = $class;
00290 }
00291 }
00292 }
00293 if (!in_array($className, $sortedClasses) && !in_array($className, $this->_processedClasses)) {
00294 $sortedClasses[] = $className;
00295 if ($scope == 'default') {
00296 $this->_processedClasses[] = $className;
00297 }
00298 }
00299 }
00300
00301 $classesSource = "<?php\n";
00302 foreach ($sortedClasses as $className) {
00303 $file = $this->_includeDir.DS.$className.'.php';
00304 if (!file_exists($file)) {
00305 continue;
00306 }
00307 $content = file_get_contents($file);
00308 $content = ltrim($content, '<?php');
00309 $content = rtrim($content, "\n\r\t?>");
00310 $classesSource.= $content;
00311 }
00312 return $classesSource;
00313 }
00314
00315 public function clear()
00316 {
00317 $this->registerIncludePath(false);
00318 if (is_dir($this->_includeDir)) {
00319 mageDelTree($this->_includeDir);
00320 }
00321 return $this;
00322 }
00323
00324
00325
00326
00327
00328
00329 public function run()
00330 {
00331 $this->_collectFiles();
00332 $this->_compileFiles();
00333 $this->registerIncludePath();
00334 return $this;
00335
00336 }
00337
00338
00339
00340
00341
00342
00343
00344 public function registerIncludePath($flag = true)
00345 {
00346 $file = $this->_compileDir.DS.'config.php';
00347 if (is_writeable($file)) {
00348 $content = file_get_contents($file);
00349 $content = explode("\n", $content);
00350 foreach ($content as $index => $line) {
00351 if (strpos($line, 'COMPILER_INCLUDE_PATH')) {
00352 if ($flag) {
00353 $content[$index] = ltrim($line, '#');
00354 } else {
00355 $content[$index] = '#'.$line;
00356 }
00357 }
00358 }
00359 file_put_contents($file, implode("\n", $content));
00360 }
00361 return $this;
00362 }
00363
00364
00365
00366
00367
00368
00369 public function validate()
00370 {
00371 $result = array();
00372 if (!is_writeable($this->_compileDir)) {
00373 $result[] = Mage::helper('compiler')->__('Directory "%s" must be writeable', $this->_includeDir);
00374 }
00375 $file = $this->_compileDir.DS.'config.php';
00376 if (!is_writeable($file)) {
00377 $result[] = Mage::helper('compiler')->__('File "%s" must be writeable', $file);
00378 }
00379 return $result;
00380 }
00381
00382 }