/modules/main/lib/db/result.php
PHP | 328 lines | 166 code | 34 blank | 128 comment | 20 complexity | 06362f3b6050367040fe5a07b2564b60 MD5 | raw file
- <?php
- namespace Bitrix\Main\DB;
- /**
- * Class Result is the abstract base class for representing
- * database query result.
- * <p>
- * It has ability to transform raw data populated from
- * the database into useful associative arrays with
- * some fields unserialized and some presented as Datetime
- * objects or other changes.
- * <p>
- * It also supports query debugging by providing {@link \Bitrix\Main\Diag\SqlTracker}
- * with timing information.
- *
- * @package Bitrix\Main\DB
- */
- abstract class Result implements \IteratorAggregate
- {
- /** @var \Bitrix\Main\DB\Connection */
- protected $connection;
- /** @var resource */
- protected $resource;
- /** @var \Bitrix\Main\Diag\SqlTrackerQuery */
- protected $trackerQuery = null;
- /** @var callable[] */
- protected $converters = array();
- /** @var string[] */
- protected $serializedFields = array();
- /** @var string[] */
- protected $replacedAliases = array();
- /** @var callable[] */
- protected $fetchDataModifiers = array();
- /** @var int */
- protected $count;
- /**
- * @param resource $result Database-specific query result.
- * @param Connection $dbConnection Connection object.
- * @param \Bitrix\Main\Diag\SqlTrackerQuery $trackerQuery Helps to collect debug information.
- */
- public function __construct($result, Connection $dbConnection = null, \Bitrix\Main\Diag\SqlTrackerQuery $trackerQuery = null)
- {
- $this->resource = $result;
- $this->connection = $dbConnection;
- $this->trackerQuery = $trackerQuery;
- $resultFields = $this->getFields();
- if ($resultFields && $this->connection)
- {
- $helper = $this->connection->getSqlHelper();
- foreach ($resultFields as $key => $type)
- {
- $converter = $helper->getConverter($resultFields[$key]);
- if (is_callable($converter))
- {
- $this->converters[$key] = $converter;
- }
- }
- }
- }
- /**
- * Returns database-specific resource of this result.
- *
- * @return null|resource
- */
- public function getResource()
- {
- return $this->resource;
- }
- /**
- * Sets list of aliased columns.
- * This allows to overcome database limits on length of the column names.
- *
- * @param array[string]string $replacedAliases Aliases map from tech to human.
- *
- * @return void
- * @see \Bitrix\Main\Db\Result::addReplacedAliases
- */
- public function setReplacedAliases(array $replacedAliases)
- {
- $this->replacedAliases = $replacedAliases;
- }
- /**
- * Extends list of aliased columns.
- *
- * @param array[string]string $replacedAliases Aliases map from tech to human.
- *
- * @return void
- * @see \Bitrix\Main\Db\Result::setReplacedAliases
- */
- public function addReplacedAliases(array $replacedAliases)
- {
- $this->replacedAliases = array_merge($this->replacedAliases, $replacedAliases);
- }
- /**
- * Sets internal list of fields which will be unserialized on fetch.
- *
- * @param array $serializedFields List of fields.
- *
- * @return void
- */
- public function setSerializedFields(array $serializedFields)
- {
- $this->serializedFields = $serializedFields;
- }
- /**
- * Modifier should accept once fetched array as an argument, then modify by link or return new array:
- * - function (&$data) { $data['AGE'] -= 7; }
- * - function ($data) { $data['AGE'] -= 7; return $data; }
- *
- * @param callable $fetchDataModifier Valid callback.
- *
- * @return void
- * @throws \Bitrix\Main\ArgumentException
- */
- public function addFetchDataModifier($fetchDataModifier)
- {
- if (!is_callable($fetchDataModifier))
- {
- throw new \Bitrix\Main\ArgumentException('Data Modifier should be a callback');
- }
- $this->fetchDataModifiers[] = $fetchDataModifier;
- }
- /**
- * Fetches one row of the query result and returns it in the associative array of raw DB data or false on empty data.
- *
- * @return array|false
- */
- public function fetchRaw()
- {
- if ($this->trackerQuery != null)
- {
- $this->trackerQuery->restartQuery();
- }
- $data = $this->fetchRowInternal();
- if ($this->trackerQuery != null)
- {
- $this->trackerQuery->refinishQuery();
- }
- if (!$data)
- {
- return false;
- }
- return $data;
- }
- /**
- * Fetches one row of the query result and returns it in the associative array of converted data or false on empty data.
- *
- * @param \Bitrix\Main\Text\Converter $converter Optional converter to encode data on fetching.
- *
- * @return array|false
- */
- public function fetch(\Bitrix\Main\Text\Converter $converter = null)
- {
- $data = $this->fetchRaw();
- if (!$data)
- {
- return false;
- }
- if ($this->converters)
- {
- foreach ($this->converters as $field => $convertDataModifier)
- {
- $data[$field] = call_user_func_array($convertDataModifier, array($data[$field]));
- }
- }
- if ($this->serializedFields)
- {
- foreach ($this->serializedFields as $field)
- {
- if (isset($data[$field]))
- $data[$field] = unserialize($data[$field]);
- }
- }
- if ($this->replacedAliases)
- {
- foreach ($this->replacedAliases as $tech => $human)
- {
- $data[$human] = $data[$tech];
- unset($data[$tech]);
- }
- }
- if ($this->fetchDataModifiers)
- {
- foreach ($this->fetchDataModifiers as $fetchDataModifier)
- {
- $result = call_user_func_array($fetchDataModifier, array(&$data));
- if (is_array($result))
- {
- $data = $result;
- }
- }
- }
- if ($converter != null)
- {
- foreach ($data as $key => $val)
- {
- $data[$key] = $converter->encode(
- $val,
- (isset($data[$key."_TYPE"])? $data[$key."_TYPE"] : \Bitrix\Main\Text\Converter::TEXT)
- );
- }
- }
- return $data;
- }
- /**
- * Fetches all the rows of the query result and returns it in the array of associative arrays.
- * Returns an empty array if query has no data.
- *
- * @param \Bitrix\Main\Text\Converter $converter Optional converter to encode data on fetching.
- *
- * @return array
- */
- public function fetchAll(\Bitrix\Main\Text\Converter $converter = null)
- {
- $res = array();
- while ($ar = $this->fetch($converter))
- {
- $res[] = $ar;
- }
- return $res;
- }
- /**
- * Returns an array of fields according to columns in the result.
- *
- * @return \Bitrix\Main\ORM\Fields\ScalarField[]
- */
- abstract public function getFields();
- /**
- * Returns the number of rows in the result.
- *
- * @return int
- */
- abstract public function getSelectedRowsCount();
- /**
- * Returns next result row or false.
- *
- * @return array|false
- */
- abstract protected function fetchRowInternal();
- /**
- * Returns current query tracker.
- *
- * @return \Bitrix\Main\Diag\SqlTrackerQuery|null
- */
- public function getTrackerQuery()
- {
- return $this->trackerQuery;
- }
- /**
- * @return callable[]
- */
- public function getConverters()
- {
- return $this->converters;
- }
- /**
- * @param callable[] $converters
- */
- public function setConverters($converters)
- {
- $this->converters = $converters;
- }
- /**
- * Sets record count.
- * @param int $n
- */
- public function setCount($n)
- {
- $this->count = (int)$n;
- }
- /**
- * Returns record count. It's required to set record count explicitly before.
- * @return int
- * @throws \Bitrix\Main\ObjectPropertyException
- */
- public function getCount()
- {
- if($this->count !== null)
- {
- return $this->count;
- }
- throw new \Bitrix\Main\ObjectPropertyException("count");
- }
- /**
- * Retrieve an external iterator
- * @link http://php.net/manual/en/iteratoraggregate.getiterator.php
- * @return \Traversable An instance of an object implementing <b>Iterator</b> or
- * <b>Traversable</b>
- * @since 5.0.0
- */
- public function getIterator()
- {
- return new ResultIterator($this);
- }
- }