mirror of
https://github.com/e107inc/e107.git
synced 2025-08-03 21:27:25 +02:00
Merge pull request #3066 from Deltik/fix-3062
e_tree_model performance improvements
This commit is contained in:
@@ -4364,8 +4364,6 @@ class e_admin_controller_ui extends e_admin_controller
|
|||||||
public function getParentChildQry($orderby=false)
|
public function getParentChildQry($orderby=false)
|
||||||
{
|
{
|
||||||
return "SELECT SQL_CALC_FOUND_ROWS * FROM `#".$this->getTableName()."` ";
|
return "SELECT SQL_CALC_FOUND_ROWS * FROM `#".$this->getTableName()."` ";
|
||||||
// Use the following return statement to break e107 native sorting but speed up tree creation by presorting for e_tree_model::arrayToTree()
|
|
||||||
#return "SELECT SQL_CALC_FOUND_ROWS * FROM `#".$this->getTableName()."` ORDER BY ".$this->getSortParent().", ".$this->getSortField();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -3337,26 +3337,8 @@ class e_tree_model extends e_front_model
|
|||||||
$sql = e107::getDb($this->getParam('model_class', 'e_model'));
|
$sql = e107::getDb($this->getParam('model_class', 'e_model'));
|
||||||
$this->_total = $sql->total_results = false;
|
$this->_total = $sql->total_results = false;
|
||||||
|
|
||||||
// Workaround: Parse and modify db_query param for simulated pagination
|
if($rows = $this->getRows($sql))
|
||||||
$this->prepareSimulatedPagination();
|
|
||||||
// Workaround: Parse and modify db_query param for simulated custom ordering
|
|
||||||
$this->prepareSimulatedCustomOrdering();
|
|
||||||
|
|
||||||
if($sql->gen($this->getParam('db_query'), $this->getParam('db_debug') ? true : false))
|
|
||||||
{
|
{
|
||||||
$rows_tree = self::arrayToTree($sql->rows(),
|
|
||||||
$this->getParam('primary_field'),
|
|
||||||
$this->getParam('sort_parent'));
|
|
||||||
$rows = self::flattenTree($rows_tree,
|
|
||||||
$this->getParam('sort_field'),
|
|
||||||
$this->getParam('sort_order'));
|
|
||||||
|
|
||||||
// Simulated pagination
|
|
||||||
$rows = array_splice($rows,
|
|
||||||
(int) $this->getParam('db_limit_offset'),
|
|
||||||
($this->getParam('db_limit_count') ? $this->getParam('db_limit_count') : count($rows))
|
|
||||||
);
|
|
||||||
|
|
||||||
foreach($rows as $tmp)
|
foreach($rows as $tmp)
|
||||||
{
|
{
|
||||||
$tmp = new $class_name($tmp);
|
$tmp = new $class_name($tmp);
|
||||||
@@ -3387,6 +3369,51 @@ class e_tree_model extends e_front_model
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getRows($sql)
|
||||||
|
{
|
||||||
|
// Tree (Parent-Child Relationship)
|
||||||
|
if ($this->getParam('sort_parent') && $this->getParam('sort_field'))
|
||||||
|
{
|
||||||
|
return $this->getRowsTree($sql);
|
||||||
|
}
|
||||||
|
// Flat List
|
||||||
|
return $this->getRowsList($sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getRowsList($sql)
|
||||||
|
{
|
||||||
|
$success = $sql->gen($this->getParam('db_query'), $this->getParam('db_debug') ? true : false);
|
||||||
|
if (!$success) return false;
|
||||||
|
|
||||||
|
return $sql->rows();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getRowsTree($sql)
|
||||||
|
{
|
||||||
|
// Workaround: Parse and modify db_query param for simulated pagination
|
||||||
|
$this->prepareSimulatedPagination();
|
||||||
|
// Workaround: Parse and modify db_query param for simulated custom ordering
|
||||||
|
$this->prepareSimulatedCustomOrdering();
|
||||||
|
|
||||||
|
$success = $sql->gen($this->getParam('db_query'), $this->getParam('db_debug') ? true : false);
|
||||||
|
if (!$success) return false;
|
||||||
|
|
||||||
|
$rows_tree = self::arrayToTree($sql->rows(),
|
||||||
|
$this->getParam('primary_field'),
|
||||||
|
$this->getParam('sort_parent'));
|
||||||
|
$rows = self::flattenTree($rows_tree,
|
||||||
|
$this->getParam('sort_field'),
|
||||||
|
$this->getParam('sort_order'));
|
||||||
|
|
||||||
|
// Simulated pagination
|
||||||
|
$rows = array_splice($rows,
|
||||||
|
(int) $this->getParam('db_limit_offset'),
|
||||||
|
($this->getParam('db_limit_count') ? $this->getParam('db_limit_count') : count($rows))
|
||||||
|
);
|
||||||
|
|
||||||
|
return $rows;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a relational array with a parent field and a sort order field to a tree
|
* Converts a relational array with a parent field and a sort order field to a tree
|
||||||
* @param array $rows Relational array with a parent field and a sort order field
|
* @param array $rows Relational array with a parent field and a sort order field
|
||||||
@@ -3420,17 +3447,21 @@ class e_tree_model extends e_front_model
|
|||||||
{
|
{
|
||||||
$node = &$nodes[0];
|
$node = &$nodes[0];
|
||||||
array_shift($nodes);
|
array_shift($nodes);
|
||||||
|
$nodeID = (int) $node[$primary_field];
|
||||||
foreach($rows as $key => $row)
|
foreach($rows as $key => $row)
|
||||||
{
|
{
|
||||||
$nodeID = (int) $node[$primary_field];
|
|
||||||
$rowParentID = (int) $row[$sort_parent];
|
$rowParentID = (int) $row[$sort_parent];
|
||||||
if($nodeID === $rowParentID)
|
|
||||||
|
// Note: This optimization only works if the SQL query executed was ordered by the sort parent.
|
||||||
|
if($nodeID !== $rowParentID)
|
||||||
{
|
{
|
||||||
$node['_children'][] = &$row;
|
break;
|
||||||
unset($rows[$key]);
|
|
||||||
$nodes[] = &$row;
|
|
||||||
unset($row);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$node['_children'][] = &$row;
|
||||||
|
unset($rows[$key]);
|
||||||
|
$nodes[] = &$row;
|
||||||
|
unset($row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3568,21 +3599,26 @@ class e_tree_model extends e_front_model
|
|||||||
{
|
{
|
||||||
$db_query = $this->getParam('db_query');
|
$db_query = $this->getParam('db_query');
|
||||||
$db_query = preg_replace_callback('/ORDER BY (?:.+\.)*[\.]*([A-Za-z0-9$_,]+)[ ]*(ASC|DESC)*/i', function($matches)
|
$db_query = preg_replace_callback('/ORDER BY (?:.+\.)*[\.]*([A-Za-z0-9$_,]+)[ ]*(ASC|DESC)*/i', function($matches)
|
||||||
{
|
|
||||||
if (isset($matches[1]))
|
|
||||||
{
|
{
|
||||||
$current_sort_field = $this->getParam('sort_field');
|
if (!empty($matches[1]))
|
||||||
if (!empty($current_sort_field))
|
|
||||||
{
|
{
|
||||||
$matches[1] = $current_sort_field.",".$matches[1];
|
$current_sort_field = $this->getParam('sort_field');
|
||||||
|
if (!empty($current_sort_field))
|
||||||
|
{
|
||||||
|
$matches[1] = $current_sort_field.",".$matches[1];
|
||||||
|
}
|
||||||
|
$this->setParam('sort_field', array_map('trim', explode(',', $matches[1])));
|
||||||
}
|
}
|
||||||
$this->setParam('sort_field', array_map('trim', explode(',', $matches[1])));
|
if (!empty($matches[2]))
|
||||||
}
|
$this->setParam('sort_order',
|
||||||
if (isset($matches[2]))
|
(0 === strcasecmp($matches[2], 'DESC') ? -1 : 1)
|
||||||
$this->setParam('sort_order',
|
);
|
||||||
(0 === strcasecmp($matches[2], 'DESC') ? -1 : 1)
|
|
||||||
);
|
return "";
|
||||||
}, $db_query);
|
}, $db_query)
|
||||||
|
// Optimization goes with e_tree_model::moveRowsToTreeNodes()
|
||||||
|
. " ORDER BY " . $this->getParam('sort_parent') . ", " . $this->getParam('sort_field');
|
||||||
|
$this->setParam('db_query', $db_query);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user