Commit 38aded21 authored by Ad Schellevis's avatar Ad Schellevis

(menu) improve menu parsing performance

parent 5069d99c
......@@ -96,6 +96,24 @@ class MenuItem
*/
private $selected = false;
/**
* class method getters
* @var array
*/
private static $internalClassGetterNames = null;
/**
* class method setters
* @var array
*/
private static $internalClassSetterNames = null;
/**
* map internal methods to support faster case-insensitive matching
* @var array|null
*/
private static $internalClassMethodAliases = null;
/**
* Find setter for property, ignore case
* @param string $name property name
......@@ -103,14 +121,16 @@ class MenuItem
*/
private function getXmlPropertySetterName($name)
{
$class_methods = get_class_methods($this);
foreach ($class_methods as $method_name) {
if ("set".strtolower($name) == strtolower($method_name)) {
return $method_name;
if (!isset(self::$internalClassMethodAliases[$name])) {
self::$internalClassMethodAliases[$name] = null;
$propKey = strtolower($name);
foreach (self::$internalClassSetterNames as $methodName => $propValue) {
if ($propKey == strtolower($propValue)) {
self::$internalClassMethodAliases[$name] = $methodName;
}
}
}
return null;
return self::$internalClassMethodAliases[$name];
}
/**
......@@ -123,6 +143,23 @@ class MenuItem
$this->id = $id;
$this->visibleName = $id;
$this->parent = $parent;
$prop_exclude_list = array("getXmlPropertySetterName" => true);
if (self::$internalClassMethodAliases === null) {
self::$internalClassMethodAliases = array();
self::$internalClassSetterNames = array();
self::$internalClassGetterNames = array();
// cache method names, get_class_methods() should always return the initial methods.
// Caching the methods delivers quite some performance at minimal memory cost.
foreach (get_class_methods($this) as $methodName) {
if (!isset($prop_exclude_list[$methodName])) {
if (substr($methodName, 0, 3) == "get") {
self::$internalClassGetterNames[$methodName] = substr($methodName, 3);
} elseif (substr($methodName, 0, 3) == "set") {
self::$internalClassSetterNames[$methodName] = substr($methodName, 3);
}
}
}
}
}
/**
......@@ -277,7 +314,9 @@ class MenuItem
// set attributes
foreach ($properties as $propname => $propvalue) {
$methodName = $newMenuItem->getXmlPropertySetterName($propname);
$newMenuItem->$methodName((string)$propvalue);
if ($methodName !== null) {
$newMenuItem->$methodName((string)$propvalue);
}
}
$orderNum = sprintf("%05d", $newMenuItem->getOrder());
......@@ -377,20 +416,10 @@ class MenuItem
public function getChildren()
{
$result = array();
$properties = array();
// probe this object for available setters, so we know what to publish to the outside world.
$prop_exclude_list = array("getXmlPropertySetterName");
$class_methods = get_class_methods($this);
foreach ($class_methods as $method_name) {
if (substr($method_name, 0, 3) == "get" && in_array($method_name, $prop_exclude_list) == false) {
$properties[$method_name] = substr($method_name, 3);
}
}
// sort by order/id and map getters to array items
foreach ($this->getFilteredChildren() as $key => $node) {
$result[$node->id] = new \stdClass();
foreach ($properties as $methodName => $propName) {
foreach (self::$internalClassGetterNames as $methodName => $propName) {
$result[$node->id]->{$propName} = $node->$methodName();
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment