icingaweb2/library/Icinga/Protocol/File/Reader.php

260 lines
6.7 KiB
PHP
Raw Normal View History

2014-03-19 16:57:11 +01:00
<?php
namespace Icinga\Protocol\File;
use Icinga\Data\DatasourceInterface;
class Reader implements DatasourceInterface
{
private $filename;
private $config;
public function __construct($config)
{
$this->config = $config;
$this->filename = $config->filename;
}
2014-04-01 16:29:09 +02:00
/**
* Instantiate a Query object
*
* @return Query
*/
2014-03-19 16:57:11 +01:00
public function select()
{
return new Query($this);
}
2014-04-01 16:29:09 +02:00
/**
* Fetch result as an array of objects
*
* @return array
*/
2014-03-19 16:57:11 +01:00
public function fetchAll(Query $query)
{
$all = array();
foreach ($this->fetchPairs($query) as $index => $value) {
$all[$index] = new \stdClass();
foreach ($value as $key => $value_2) {
$all[$index]->{$key} = $value_2;
}
}
return $all;
}
2014-04-01 16:29:09 +02:00
/**
* Fetch first result row
*
* @return object
*/
2014-03-19 16:57:11 +01:00
public function fetchRow(Query $query)
{
$all = $this->fetchAll($query);
if (isset($all[0])) {
return $all[0];
}
return null;
}
2014-04-01 16:29:09 +02:00
/**
* Fetch first result column
*
* @return array
*/
2014-03-19 16:57:11 +01:00
public function fetchColumn(Query $query)
{
$column = array();
foreach ($this->fetchPairs($query) as $value) {
foreach ($value as $value_2) {
$column[] = $value_2;
break;
}
}
return $column;
}
2014-04-01 16:29:09 +02:00
/**
* Fetch first column value from first result row
*
* @return mixed
*/
2014-03-19 16:57:11 +01:00
public function fetchOne(Query $query)
{
$pairs = $this->fetchPairs($query);
if (isset($pairs[0])) {
foreach ($pairs[0] as $value) {
return $value;
}
}
return null;
}
2014-04-01 16:29:09 +02:00
/**
* Fetch result as a key/value pair array
*
* @return array
*/
2014-03-19 16:57:11 +01:00
public function fetchPairs(Query $query)
{
return $this->read($query);
}
2014-04-01 16:29:09 +02:00
/**
* If given $line matches the $query's PCRE pattern and contains all the strings in the $query's filters array,
* return an associative array of the matches of the PCRE pattern.
* Otherwise, return false.
* If preg_match returns false, it failed parsing the PCRE pattern.
* In that case, throw an exception.
*
* @param string $line
* @param Query $query
*
* @return array|bool
*
* @throws \Exception
*/
2014-03-19 17:37:37 +01:00
public function validateLine($line, Query $query)
2014-03-19 16:57:11 +01:00
{
$data = array();
$PCRE_result = @preg_match($this->config->fields, $line, $data);
if ($PCRE_result === false) {
throw new \Exception('Failed parsing regular expression!');
} else if ($PCRE_result === 1) {
2014-03-19 17:37:37 +01:00
foreach ($query->getFilters() as $filter) {
2014-03-19 16:57:11 +01:00
if (strpos($line, $filter) === false) {
return false;
}
}
foreach ($data as $key => $value) {
if (is_int($key)) {
unset($data[$key]);
}
}
return $data;
}
return false;
}
2014-04-01 16:29:09 +02:00
/**
* Skip and read as many lines as needed according to given $query.
*
* @param Query $query
*
* @return array result
*/
2014-03-19 16:57:11 +01:00
public function read(Query $query)
{
$skip_lines = $query->getOffset();
$read_lines = $query->getLimit();
if ($skip_lines === null) {
$skip_lines = 0;
}
2014-04-01 16:29:09 +02:00
return $this->{$query->sortDesc() ? 'readFromEnd' : 'readFromStart'}($skip_lines, $read_lines, $query);
2014-03-19 16:57:11 +01:00
}
2014-04-01 16:29:09 +02:00
/**
* Backend for $this->read
*/
public function readFromEnd($skip_lines, $read_lines, Query $query)
2014-03-19 16:57:11 +01:00
{
$PHP_EOL_len = strlen(PHP_EOL);
$lines = array();
$s = '';
$f = fopen($this->filename, 'rb');
fseek($f, 0, SEEK_END);
$pos = ftell($f);
while ($read_lines === null || count($lines) < $read_lines) {
fseek($f, --$pos);
$c = fgetc($f);
if ($c === false || $pos < 0) {
2014-03-19 17:37:37 +01:00
$l = $this->validateLine($s, $query);
2014-03-19 16:57:11 +01:00
if (!($l === false || $skip_lines)) {
$lines[] = $l;
}
break;
}
$s = $c . $s;
if (strpos($s, PHP_EOL) === 0) {
2014-03-19 17:37:37 +01:00
$l = $this->validateLine((string)substr($s, $PHP_EOL_len), $query);
2014-03-19 16:57:11 +01:00
if ($l !== false) {
if ($skip_lines) {
$skip_lines--;
} else {
$lines[] = $l;
}
}
$s = '';
}
}
return $lines;
}
2014-04-01 16:29:09 +02:00
/**
* Backend for $this->read
*/
public function readFromStart($skip_lines, $read_lines, Query $query)
2014-03-19 16:57:11 +01:00
{
$PHP_EOL_len = strlen(PHP_EOL);
$lines = array();
$s = '';
$f = fopen($this->filename, 'rb');
while ($read_lines === null || count($lines) < $read_lines) {
$c = fgetc($f);
if ($c === false) {
2014-03-19 17:37:37 +01:00
$l = $this->validateLine($s, $query);
2014-03-19 16:57:11 +01:00
if (!($l === false || $skip_lines)) {
$lines[] = $l;
}
break;
}
$s .= $c;
if (strpos($s, PHP_EOL) !== false) {
2014-03-19 17:37:37 +01:00
$l = $this->validateLine((string)substr($s, 0, strlen($s) - $PHP_EOL_len), $query);
2014-03-19 16:57:11 +01:00
if ($l !== false) {
if ($skip_lines) {
$skip_lines--;
} else {
$lines[] = $l;
}
}
$s = '';
}
}
return $lines;
}
2014-04-01 16:29:09 +02:00
/**
* Return the number of available valid lines.
*
* @param Query $query
*
* @return int
*/
2014-03-19 17:37:37 +01:00
public function count(Query $query) {
2014-03-19 16:57:11 +01:00
$PHP_EOL_len = strlen(PHP_EOL);
$lines = 0;
$s = '';
$f = fopen($this->filename, 'rb');
fseek($f, 0, SEEK_END);
$pos = ftell($f);
while (true) {
fseek($f, --$pos);
$c = fgetc($f);
if ($c === false || $pos < 0) {
2014-03-19 17:37:37 +01:00
if ($this->validateLine($s, $query) !== false) {
2014-03-19 16:57:11 +01:00
$lines++;
}
break;
}
$s = $c . $s;
if (strpos($s, PHP_EOL) === 0) {
2014-03-19 17:37:37 +01:00
if ($this->validateLine((string)substr($s, $PHP_EOL_len), $query) !== false) {
2014-03-19 16:57:11 +01:00
$lines++;
}
$s = '';
}
}
return $lines;
}
}