/** * Helper function which detects if given widget is matching with * the attributes, described in the splitted part of the selector. * * For example for selector * <pre><code> * ->f("#text")->.... * </code></pre> * * each widget will be checked if it's ID is exactly equals to "text". * * Such as {@link matched} method it returns _CACHE , _NOCACHE * values, which are easily converting to bool. * * @param WComponent widget to be checked by the attributes list * @param array of parsed selector's parameters * @return mixed values, casting to bool */ protected static function matchAttributes(WComponent $widget, $parsed_selector) { if (empty($parsed_selector)) { return false; } $controller = Controller::getInstance(); //id, quick if (isset($parsed_selector['id']) && $widget->getIdLower() != $parsed_selector['id']) { return self::FALSE_CACHE; } //id starts with if (isset($parsed_selector['starts_with']) && substr($widget->getIdLower(), 0, strlen($parsed_selector['starts_with'])) != $parsed_selector['starts_with']) { return self::FALSE_CACHE; } // tag if (isset($parsed_selector['tag']) && $parsed_selector['tag'] !== "*" && $widget->getClassLower() !== $parsed_selector['tag']) { return self::FALSE_CACHE; } // .class if (isset($parsed_selector['class']) && !in_array(strtolower($parsed_selector['class']), array_map('strtolower', preg_split("/\\s+/", $widget->getStyleClass())), true)) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } // [attribute] if (isset($parsed_selector['attr'])) { if (!isset($parsed_selector['attr_value'])) { if (!method_exists($widget, "get" . $parsed_selector['attr']) || $widget->{"get" . $parsed_selector['attr']}() === null) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } } elseif (isset($parsed_selector['attr_value']) && isset($parsed_selector['attr_quant'])) { // [attr=val] if ($parsed_selector['attr_quant'] === "=") { if (!method_exists($widget, "get" . $parsed_selector['attr']) || trim($widget->{"get" . $parsed_selector['attr']}()) != strtolower($parsed_selector['attr_value'])) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } } elseif ($parsed_selector['attr_quant'] === "~=") { if (!method_exists($widget, "get" . $parsed_selector['attr']) || !in_array(strtolower($parsed_selector['attr_value']), array_map('strtolower', preg_split("/\\s+/", trim($widget->{"get" . $parsed_selector['attr']}()))), true)) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } } elseif ($parsed_selector['attr_quant'] === "!=") { if (!method_exists($widget, "get" . $parsed_selector['attr']) || trim($widget->{"get" . $parsed_selector['attr']}()) == strtolower($parsed_selector['attr_value'])) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } } elseif ($parsed_selector['attr_quant'] === "^=") { if (!method_exists($widget, "get" . $parsed_selector['attr']) || stripos(trim($widget->{"get" . $parsed_selector['attr']}()), $parsed_selector['attr_value']) !== 0) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } } elseif ($parsed_selector['attr_quant'] === "\$=") { if (!method_exists($widget, "get" . $parsed_selector['attr']) || stripos($_s = trim($widget->{"get" . $parsed_selector['attr']}()), $parsed_selector['attr_value']) !== strlen($_s) - strlen($parsed_selector['attr_value'])) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } } elseif ($parsed_selector['attr_quant'] === "*=") { if (!method_exists($widget, "get" . $parsed_selector['attr']) || stripos(trim($widget->{"get" . $parsed_selector['attr']}()), $parsed_selector['attr_value']) === false) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } } elseif ($parsed_selector['attr_quant'] === "|=") { if (!method_exists($widget, "get" . $parsed_selector['attr']) || !in_array(strtolower($parsed_selector['attr_value']), array_map('strtolower', preg_split("/\\s*-\\s*/", trim($widget->{"get" . $parsed_selector['attr']}()))), true)) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } } else { return self::FALSE_CACHE; } } } //pseudo if (isset($parsed_selector['pseudo'])) { // :contains(text) for ->getText() and ->getValue() if ($parsed_selector['pseudo'] == "contains" && isset($parsed_selector['pseudo_value'])) { if (method_exists($widget, "getText") && $widget->getText() != $parsed_selector['pseudo_value']) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } if ($widget instanceof WControl && $widget->getValue() != $parsed_selector['pseudo_value']) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "hidden") { if ($widget->getVisible()) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "visible") { if (!$widget->getVisible()) { return $widget->isInsideRoll() ? self::FALSE_NOCACHE : self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "disable") { if ($widget->getState()) { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "input") { if (!$widget instanceof WControl) { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "text") { if (!$widget instanceof WEdit || !$widget->getType() != "text") { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "password") { if (!$widget instanceof WEdit || !$widget->getType() != "password") { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "radio") { if (!$widget instanceof WRadio) { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "checkbox") { if (!$widget instanceof WCheckbox) { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "submit") { if (!$widget instanceof WButton || $widget->getType() != "submit") { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "image") { if (!$widget instanceof WButton || $widget->getType() != "image") { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "reset") { if (!$widget instanceof WButton || !$widget->getType() != "reset") { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "button") { if (!$widget instanceof WButton || !$widget->getType() != "button") { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "hidden") { if (!$widget instanceof WHidden) { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "disabled") { if (!$widget instanceof WContol || !$widget->getDisabled()) { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "enabled") { if (!$widget instanceof WContol || $widget->getDisabled()) { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "checked") { if (!$widget instanceof WCheckbox || !$widget->getChecked()) { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "first-child") { if (($parent = $controller->getAdjacencyList()->getParentForId($widget->getId())) === null) { return self::FALSE_CACHE; } if (($list = $controller->getAdjacencyList()->getChildren($parent)) && $controller->getAdjacencyList()->checkIndex($list, $widget->getId()) !== 0) { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "last-child") { if (($parent = $controller->getAdjacencyList()->getParentForId($widget->getId())) === null) { return self::FALSE_CACHE; } if (($list = $controller->getAdjacencyList()->getChildren($parent)) && $controller->getAdjacencyList()->checkIndex($list, $widget->getId()) !== count($list) - 1) { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "nth-child") { if (($parent = $controller->getAdjacencyList()->getParentForId($widget->getId())) === null || !isset($parsed_selector['pseudo_value'])) { return self::FALSE_CACHE; } $ind = ($list = $controller->getAdjacencyList()->getChildren($parent)) ? $controller->getAdjacencyList()->checkIndex($list, $widget->getId()) : -2; if (is_numeric($parsed_selector['pseudo_value'])) { return $ind !== abs($parsed_selector['pseudo_value']) - 1 ? self::FALSE_CACHE : self::TRUE_CACHE; } elseif ($parsed_selector['pseudo_value'] == "odd") { return $ind % 2 ? self::FALSE_CACHE : self::TRUE_CACHE; } elseif ($parsed_selector['pseudo_value'] == "even") { return !$ind % 2 ? self::FALSE_CACHE : self::TRUE_CACHE; } else { return self::FALSE_CACHE; } } elseif ($parsed_selector['pseudo'] === "index" && $widget->isInsideRoll()) { if (!isset($parsed_selector['pseudo_value'])) { return self::FALSE_CACHE; } $w2 = $widget; $parent = null; // inconvinient in case of nested rolls // to select odd rows, for example, "wroll > wtablerow:odd" syntax should be used if (($parent = $controller->getAdjacencyList()->getParentIterableForId($w2->getId())) === null) { while ($w2 && ($p = $controller->getAdjacencyList()->getParentForId($w2->getId())) !== null) { if ($controller->getWidget($p) instanceof iIterableContainer) { $parent = $p; break; } else { $w2 = $controller->getWidget($p); } } if ($parent == null) { return self::FALSE_CACHE; } $controller->getAdjacencyList()->setParentIterableForIdCache($widget->getId(), $parent); } if (!is_array($parsed_selector['pseudo_value'])) { if (strpos($parsed_selector['pseudo_value'], ":") !== false) { list($parsed_selector['pseudo_value'], $parsed_selector['scope']) = explode(":", $parsed_selector['pseudo_value']); } if (!isset($parsed_selector['scope'])) { $parsed_selector['scope'] = "global"; } $current = $controller->getDisplayModeParams()->getCurrent($parent, $parsed_selector['scope']); if (is_numeric($parsed_selector['pseudo_value']) && $parsed_selector['pseudo_value'] != $current) { return self::FALSE_NOCACHE; } if ($parsed_selector['pseudo_value'] === "odd" && $current % 2 !== 1) { return self::FALSE_NOCACHE; } if ($parsed_selector['pseudo_value'] === "even" && $current % 2 !== 0) { return self::FALSE_NOCACHE; } if ($parsed_selector['pseudo_value'] === "first" && !$controller->getDisplayModeParams()->isFirst($parent, $parsed_selector['scope'])) { return self::FALSE_NOCACHE; } if ($parsed_selector['pseudo_value'] === "last" && !$controller->getDisplayModeParams()->isLast($parent, $parsed_selector['scope'])) { return self::FALSE_NOCACHE; } } elseif (!count($parsed_selector['pseudo_value'])) { return self::FALSE_CACHE; } else { $controller->getDisplayModeParams()->setMatchedIndex(-1); $cur_scope = array_shift($parsed_selector['scope']); $matched = $current = $controller->getDisplayModeParams()->getCurrent($parent, $cur_scope); foreach ($parsed_selector['pseudo_value'] as $k => $v) { if (is_numeric($k) && $k != $current) { continue; } elseif ($current != RSIndexer::getLastIndex($k)) { continue; } else { $_w3 = $_w2 = $controller->getWidget($parent); $flag = true; $_parent = null; foreach (RSIndexer::toArray($k) as $next_index) { if (($_parent = $controller->getAdjacencyList()->getParentIterableForId($_w2->getId())) === null) { while ($_w2 && ($_p = $controller->getAdjacencyList()->getParentForId($_w2->getId())) !== null) { if ($controller->getWidget($_p) instanceof iIterableContainer) { $_parent = $_p; break; } else { $_w2 = $controller->getWidget($_p); } } $controller->getAdjacencyList()->setParentIterableForIdCache($_w3->getId(), $_parent); } if ($_parent && $controller->getDisplayModeParams()->getCurrent($_parent, $cur_scope) != $next_index) { $flag = false; break; } } if ($flag) { $controller->getDisplayModeParams()->setMatchedIndex($k); return self::TRUE_NOCACHE; } } } return self::FALSE_NOCACHE; } } else { return self::FALSE_CACHE; } } return self::TRUE_NOCACHE; }