1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255:
<?php
include_once(__DIR__.'/Completer.php');
class Packager_Php_Scripts_Order extends Packager_Php_Scripts_Completer
{
protected function completePhpFilesOrder () {
$this->filesPhpOrder = array();
$this->_orderDependenciesByCounts();
$this->_orderPhpFilesByDependencies();
$this->_orderPhpFilesByPreferedConfiguration('includeFirst');
$this->_orderPhpFilesByPreferedConfiguration('includeLast');
$this->filesPhpDependencies = array();
}
private function _orderDependenciesByCounts () {
uasort($this->filesPhpDependencies, function ($a, $b) {
if ($a->requiresCount == $b->requiresCount) {
if ($a->requiredByCount == $b->requiredByCount) return 0;
return ($a->requiredByCount > $b->requiredByCount) ? -1 : 1;
}
return ($a->requiresCount < $b->requiresCount) ? -1 : 1;
});
}
private function _orderPhpFilesByDependencies () {
$filesPhpDependenciesCountLast = 0;
$success = FALSE;
while (TRUE) {
$filesPhpDependenciesCountCurrent = count($this->filesPhpDependencies);
if ($filesPhpDependenciesCountCurrent == $filesPhpDependenciesCountLast) {
$success = FALSE;
break;
}
if (!$filesPhpDependenciesCountCurrent) {
$success = TRUE;
break;
}
$filesPhpDependenciesCountLast = $filesPhpDependenciesCountCurrent;
$this->_arangeOrderByDependenciesRequiresData();
$this->_arangeOrderByDependenciesRequiresDataWithRecursiveDetection();
$this->_arangeOrderByDependenciesRequiresAndRequiredByData();
}
if (!$success && count($this->filesPhpDependencies) > 0) {
$this->_displayErrorIfThereWasIndefinableOrderSituation();
}
$this->filesPhpOrder = array_keys($this->filesPhpOrder);
}
private function _arangeOrderByDependenciesRequiresData () {
$keysLengthLast = 0;
while (true) {
$keysToIterate = array_keys($this->filesPhpDependencies);
$keysLengthCurrent = count($keysToIterate);
if (!$keysLengthCurrent || $keysLengthCurrent == $keysLengthLast) break;
$keysLengthLast = $keysLengthCurrent;
for ($i = 0; $i < $keysLengthCurrent; $i += 1) {
$fullPath = $keysToIterate[$i];
$filesDependenciesItem = $this->filesPhpDependencies[$fullPath];
if (!$filesDependenciesItem->requiresCount) {
$this->filesPhpOrder[$fullPath] = 1;
unset($this->filesPhpDependencies[$fullPath]);
} else {
$allRequiresFilesAlreadyOrdered = TRUE;
foreach ($filesDependenciesItem->requires as $requiresItem) {
if (!isset($this->filesPhpOrder[$requiresItem])) {
$allRequiresFilesAlreadyOrdered = FALSE;
break;
}
}
if ($allRequiresFilesAlreadyOrdered) {
$this->filesPhpOrder[$fullPath] = 1;
unset($this->filesPhpDependencies[$fullPath]);
}
}
}
}
}
private function _arangeOrderByDependenciesRequiresDataWithRecursiveDetection () {
$keysLengthLast = 0;
while (true) {
$keysToIterate = array_keys($this->filesPhpDependencies);
$keysLengthCurrent = count($keysToIterate);
if (!$keysLengthCurrent || $keysLengthCurrent == $keysLengthLast) break;
$keysLengthLast = $keysLengthCurrent;
for ($i = 0; $i < $keysLengthCurrent; $i += 1) {
$fullPath = $keysToIterate[$i];
if (!isset($this->filesPhpDependencies[$fullPath])) continue;
$filesDependenciesItem = $this->filesPhpDependencies[$fullPath];
if (!$filesDependenciesItem->requiresCount) {
$this->filesPhpOrder[$fullPath] = 1;
unset($this->filesPhpDependencies[$fullPath]);
} else {
$filesToOrder = array($fullPath => 1);
$this->_getAllRequiresFilesToOrderedRecursive(
$filesDependenciesItem->requires,
$filesToOrder
);
if ($filesToOrder) {
foreach ($filesToOrder as $subFullPath => $yes) {
$this->filesPhpOrder[$subFullPath] = 1;
unset($this->filesPhpDependencies[$subFullPath]);
}
}
}
}
}
}
private function _getAllRequiresFilesToOrderedRecursive ($requires, & $filesToOrder, $level = 0) {
foreach ($requires as $require) {
if (!isset($this->filesPhpDependencies[$require])) continue;
if (isset($filesToOrder[$require])) continue;
$fileItem = $this->filesPhpDependencies[$require];
if (!$fileItem->requires) continue;
$filesToOrder = array_merge(array($require => 1), $filesToOrder);
$this->_getAllRequiresFilesToOrderedRecursive(
$fileItem->requires, $filesToOrder, $level + 1
);
}
return $filesToOrder;
}
private function _arangeOrderByDependenciesRequiresAndRequiredByData () {
$keysToIterate = array_keys($this->filesPhpDependencies);
$keysLength = count($keysToIterate);
for ($i = 0; $i < $keysLength; $i += 1) {
$unsafeOrderDetectionRequires = array();
$fullPath = $keysToIterate[$i];
$filesDependenciesItem = $this->filesPhpDependencies[$fullPath];
if (!$filesDependenciesItem->requiresCount) {
$this->filesPhpOrder[$fullPath] = 1;
unset($this->filesPhpDependencies[$fullPath]);
} else {
$allRequiresFilesAlreadyOrdered = TRUE;
foreach ($filesDependenciesItem->requires as $requiresItem) {
if (!isset($this->filesPhpOrder[$requiresItem])) {
if (in_array($requiresItem, $filesDependenciesItem->requiredBy)) {
$unsafeOrderDetectionRequires[] = $this->files->all[$requiresItem]->relPath;
} else {
$allRequiresFilesAlreadyOrdered = FALSE;
break;
}
}
}
if ($allRequiresFilesAlreadyOrdered) {
$this->filesPhpOrder[$fullPath] = 1;
unset($this->filesPhpDependencies[$fullPath]);
}
}
if (count($unsafeOrderDetectionRequires) > 0) {
$relPath = $this->files->all[$fullPath]->relPath;
if (!in_array($relPath, $this->unsafeOrderDetection)) {
$this->unsafeOrderDetection[] = $relPath;
}
foreach ($unsafeOrderDetectionRequires as $unsafeOrderDetectionRequire) {
if (!in_array($unsafeOrderDetectionRequire, $this->unsafeOrderDetection)) {
$this->unsafeOrderDetection[] = $unsafeOrderDetectionRequire;
}
}
}
}
}
private function _displayErrorIfThereWasIndefinableOrderSituation () {
$filesFullPaths = array_keys($this->filesPhpDependencies);
foreach ($this->cfg->includeFirst as $fullPath) {
$key = array_search($fullPath, $filesFullPaths);
if ($key !== FALSE) unset($filesFullPaths[$key]);
}
foreach ($this->cfg->includeLast as $fullPath) {
$key = array_search($fullPath, $filesFullPaths);
if ($key !== FALSE) unset($filesFullPaths[$key]);
}
if (count($filesFullPaths) > 0) {
ob_start();
echo '<pre>';
var_dump($filesFullPaths);
$filesFullPathsPrinted = ob_get_clean() . '</pre>';
$this->sendResult(
"There was not possible to determinate declaration order for files bellow. <br />"
."Please set order for these files manualy by config arrays in keys: <br />"
."\$config['includeFirst'] = array(...);<br />"
."\$config['includeLast'] = array(...);",
$filesFullPathsPrinted,
'error'
);
}
}
private function _orderPhpFilesByPreferedConfiguration ($cfgKey) {
if (count($this->cfg->$cfgKey) > 0) {
$filesPhpOrder = $this->filesPhpOrder;
$fullPathsToReorder = array();
foreach ($this->cfg->$cfgKey as $fullPath) {
if (is_file($fullPath)) {
if (!isset($this->files->all[$fullPath])) continue;
if ($this->files->all[$fullPath]->extension != 'php') continue;
$fullPathsToReorder[] = $fullPath;
$keyToUnset = array_search($fullPath, $filesPhpOrder);
if ($keyToUnset !== FALSE && isset($filesPhpOrder[$keyToUnset])) {
unset($filesPhpOrder[$keyToUnset]);
}
} else {
for ($i = 0, $l = count($filesPhpOrder); $i < $l; $i += 1) {
if (!isset($filesPhpOrder[$i])) continue;
$orderedFullPath = $filesPhpOrder[$i];
if (mb_strpos($orderedFullPath, $fullPath) === 0) {
$fullPathsToReorder[] = $orderedFullPath;
if (isset($filesPhpOrder[$i])) {
unset($filesPhpOrder[$i]);
}
}
}
}
}
if ($cfgKey == 'includeFirst') {
$this->filesPhpOrder = array_merge(
array_values($fullPathsToReorder),
array_values($filesPhpOrder)
);
} else {
$this->filesPhpOrder = array_merge(
array_values($filesPhpOrder),
array_values($fullPathsToReorder)
);
}
}
}
}