You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
298 lines
6.5 KiB
298 lines
6.5 KiB
1 year ago
|
<?php
|
||
|
/*
|
||
|
** Zabbix
|
||
|
** Copyright (C) 2001-2023 Zabbix SIA
|
||
|
**
|
||
|
** This program is free software; you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation; either version 2 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program; if not, write to the Free Software
|
||
|
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||
|
**/
|
||
|
|
||
|
|
||
|
require_once 'vendor/autoload.php';
|
||
|
|
||
|
require_once dirname(__FILE__).'/../CElement.php';
|
||
|
|
||
|
/**
|
||
|
* Table element.
|
||
|
*/
|
||
|
class CTableElement extends CElement {
|
||
|
|
||
|
/**
|
||
|
* Table element selectors.
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $selectors = [
|
||
|
'header' => 'xpath:./thead/tr/th',
|
||
|
'row' => 'xpath:./tbody/tr',
|
||
|
'column' => 'xpath:./*'
|
||
|
];
|
||
|
|
||
|
/**
|
||
|
* Header element collection.
|
||
|
*
|
||
|
* @var CElementCollection
|
||
|
*/
|
||
|
protected $headers;
|
||
|
|
||
|
/**
|
||
|
* Array of header element texts.
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $headers_text;
|
||
|
|
||
|
/**
|
||
|
* Array of column names.
|
||
|
*
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $column_names;
|
||
|
|
||
|
/**
|
||
|
* @inheritdoc
|
||
|
*/
|
||
|
protected function normalize() {
|
||
|
if ($this->getTagName() !== 'table') {
|
||
|
$this->setElement($this->query('xpath:.//table')->waitUntilPresent()->one());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @inheritdoc
|
||
|
*/
|
||
|
public function invalidate() {
|
||
|
parent::invalidate();
|
||
|
|
||
|
$this->headers = null;
|
||
|
$this->headers_text = null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get header element collection.
|
||
|
*
|
||
|
* @return CElementCollection
|
||
|
*/
|
||
|
public function getHeaders() {
|
||
|
if ($this->headers === null) {
|
||
|
$this->headers = $this->query($this->selectors['header'])->all();
|
||
|
}
|
||
|
|
||
|
return $this->headers;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get array of header element texts.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getHeadersText() {
|
||
|
if ($this->headers_text === null) {
|
||
|
$this->headers_text = $this->getHeaders()->asText();
|
||
|
}
|
||
|
|
||
|
return $this->headers_text;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get sortable table headers.
|
||
|
*
|
||
|
* @return CElementCollection
|
||
|
*/
|
||
|
public function getSortableHeaders() {
|
||
|
return $this->getHeaders()->query('tag:a');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get array of header element texts for column naming.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getColumnNames() {
|
||
|
if ($this->column_names === null) {
|
||
|
$this->column_names = $this->getHeadersText();
|
||
|
}
|
||
|
|
||
|
return $this->column_names;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set array of header element texts for column naming.
|
||
|
*
|
||
|
* @param array $names array of names
|
||
|
*/
|
||
|
public function setColumnNames($names) {
|
||
|
$this->column_names = $names;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get collection of table rows.
|
||
|
*
|
||
|
* @return CElementCollection
|
||
|
*/
|
||
|
public function getRows() {
|
||
|
return $this->query($this->selectors['row'])->asTableRow([
|
||
|
'parent' => $this,
|
||
|
'column_selector' => $this->selectors['column']
|
||
|
])->all();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get table row by index.
|
||
|
*
|
||
|
* @param $index row index
|
||
|
*
|
||
|
* @return CTableRow
|
||
|
*/
|
||
|
public function getRow($index) {
|
||
|
return $this->query($this->selectors['row'].'['.((int)$index + 1).']')->asTableRow([
|
||
|
'parent' => $this,
|
||
|
'column_selector' => $this->selectors['column']
|
||
|
])->one();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get indexed collections of table columns.
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function getCells() {
|
||
|
$headers = $this->getColumnNames();
|
||
|
|
||
|
$table = [];
|
||
|
foreach ($this->getRows() as $row) {
|
||
|
$data = [];
|
||
|
foreach ($row->query('xpath:./'.CXPathHelper::fromSelector($this->selectors['column']).'|./th')->all() as $i => $column) {
|
||
|
$data[CTestArrayHelper::get($headers, $i, $i)] = $column;
|
||
|
}
|
||
|
|
||
|
$table[] = new CElementCollection($data);
|
||
|
}
|
||
|
|
||
|
return $table;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Find row by column value.
|
||
|
*
|
||
|
* @param string $column column name
|
||
|
* @param string $value column value
|
||
|
* @param boolean $contains flag that determines if column value should contain the passed value or coincide with it
|
||
|
*
|
||
|
* @return CTableRow|CNullElement
|
||
|
*/
|
||
|
public function findRow($column, $value, $contains = false) {
|
||
|
$headers = $this->getColumnNames();
|
||
|
|
||
|
if (is_string($column)) {
|
||
|
$index = array_search($column, $headers);
|
||
|
if ($index === false) {
|
||
|
return new CNullElement(['locator' => '"'.$column.'" (table column name)']);
|
||
|
}
|
||
|
|
||
|
$column = $index + 1;
|
||
|
}
|
||
|
|
||
|
$suffix = $contains ? '['.$column.'][contains(string(), '.CXPathHelper::escapeQuotes($value).')]/..'
|
||
|
: '['.$column.'][string()='.CXPathHelper::escapeQuotes($value).']/..';
|
||
|
$xpaths = ['.//tbody/tr/td'.$suffix, './/tbody/tr/th'.$suffix];
|
||
|
|
||
|
return $this->query('xpath', implode('|', $xpaths))->asTableRow([
|
||
|
'parent' => $this,
|
||
|
'column_selector' => $this->selectors['column']
|
||
|
])->one(false);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Find rows by column value or by criteria in function.
|
||
|
*
|
||
|
* @param callable $param column name or function
|
||
|
* @param mixed $data row data
|
||
|
*
|
||
|
* @return CElementCollection
|
||
|
*/
|
||
|
public function findRows($param, $data = []) {
|
||
|
$rows = [];
|
||
|
|
||
|
if ($param instanceof \Closure) {
|
||
|
foreach ($this->getRows() as $i => $row) {
|
||
|
if (call_user_func($param, $row)) {
|
||
|
$rows[$i] = $row;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
if (!is_array($data)) {
|
||
|
$data = [$data];
|
||
|
}
|
||
|
|
||
|
foreach ($this->getRows() as $row) {
|
||
|
if (in_array($row->getColumnData($param, ''), $data)) {
|
||
|
$rows[] = $row;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return new CElementCollection($rows, CTableRowElement::class);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Index table row text by values of table column.
|
||
|
*
|
||
|
* @param string $column column name
|
||
|
* @param boolean $include_column flag used to include or remove column used in index
|
||
|
*
|
||
|
* @return array
|
||
|
*/
|
||
|
public function index($column = null, $include_column = false) {
|
||
|
$table = [];
|
||
|
foreach ($this->getCells() as $i => $row) {
|
||
|
$data = [];
|
||
|
$id = $i;
|
||
|
|
||
|
foreach ($row as $header => $element) {
|
||
|
$value = $element->getText();
|
||
|
|
||
|
if ($header === $column) {
|
||
|
$id = $value;
|
||
|
}
|
||
|
|
||
|
if ($include_column || $header !== $column) {
|
||
|
$data[$header] = $value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$table[$id] = $data;
|
||
|
}
|
||
|
|
||
|
return $table;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Index table rows by column text.
|
||
|
*
|
||
|
* @param mixed $column column name or index @see CTableRowElement::getColumn
|
||
|
*
|
||
|
* @return CElementCollection
|
||
|
*/
|
||
|
public function indexRows($column) {
|
||
|
$table = [];
|
||
|
foreach ($this->getRows() as $row) {
|
||
|
$table[$row->getColumn($column)->getText()] = $row;
|
||
|
}
|
||
|
|
||
|
return new CElementCollection($table, 'CTableRowElement');
|
||
|
}
|
||
|
}
|