Your IP : 3.142.174.100


Current Path : /home/bitrix/ext_www/klimatlend.ua/bitrix/modules/conversion/lib/internals/
Upload File :
Current File : /home/bitrix/ext_www/klimatlend.ua/bitrix/modules/conversion/lib/internals/basecontext.php

<?php

namespace Bitrix\Conversion\Internals;

use Bitrix\Conversion\CounterManager;
use Bitrix\Conversion\AttributeManager;

use Bitrix\Main\DB;
use Bitrix\Main\Type\Date;
use Bitrix\Main\Config\Option;
use Bitrix\Main\SystemException;
use Bitrix\Main\ArgumentTypeException;

/** @internal */
class BaseContext
{
	const EMPTY_CONTEXT_ID = 0; // Context with no attributes.

	protected $id = null;
	protected $attributes = array();

	/** Add value to counter. If counter not exists set counter to value. Save to database.
	 * @param Date      $day   - counter date
	 * @param string    $name  - counter name
	 * @param int|float $value - number to add
	 * @throws ArgumentTypeException
	 * @throws SystemException
	 */
	public function addCounter($day, $name, $value = null)
	{
		if (!($day instanceof Date))
			throw new ArgumentTypeException('day', '\Bitrix\Main\Type\Date');

		if (! is_string($name))
			throw new ArgumentTypeException('name', 'string');

		if (! is_numeric($value))
			throw new ArgumentTypeException('value', 'numeric');

		if (($id = $this->id) === null)
			throw new SystemException('Cannot add counter without context!');

		static $types;
		if (! $types)
		{
			$types = CounterManager::getTypes();
		}

		if (! $type = $types[$name])
			throw new SystemException("Undefined counter '$name' type!");

		if (! $type['ACTIVE'])
			return;

		// save to database

		$primary = array(
			'DAY'        => $day,
			'CONTEXT_ID' => $id,
			'NAME'       => $name
		);

		$data = array('VALUE' => new DB\SqlExpression('?# + ?f', 'VALUE', $value));

		$result = ContextCounterDayTable::update($primary, $data);

		if ($result->getAffectedRowsCount() === 0)
		{
			try
			{
				$result = ContextCounterDayTable::add($primary + array('VALUE' => $value));
			}
			catch (DB\SqlQueryException $e)
			{
				$result = ContextCounterDayTable::update($primary, $data);
			}
		}

		$result->isSuccess(); // TODO isSuccess
	}

	/** Set attribute with value.
	 * @param string                $name  - attribute name
	 * @param string|int|float|null $value - attribute value
	 * @throws ArgumentTypeException
	 * @throws SystemException
	 */
	public function setAttribute($name, $value = null)
	{
		if (! is_string($name))
			throw new ArgumentTypeException('name', 'string');

		if (! (is_scalar($value) || is_null($value)))
			throw new ArgumentTypeException('name', 'scalar');

		if ($this->id !== null)
			throw new SystemException('Cannot set attribute for existent context!');

		static $types;
		if (! $types)
		{
			$types = AttributeManager::getTypes();
		}

		if (! $type = $types[$name])
			throw new SystemException("Undefined attribute '$name' type!");

		// set attribute

		$this->attributes[$name] = $value;
	}

	/** Save context & attributes to database */
	protected function save()
	{
		if (($id =& $this->id) !== null)
			throw new SystemException('Cannot save existent context!');

		$id = self::EMPTY_CONTEXT_ID;

		if ($attributes = $this->attributes)
		{
			// leave only one attribute in group

			static $groupedTypes;

			if (! $groupedTypes)
			{
				$groupedTypes = AttributeManager::getGroupedTypes();
				unset($groupedTypes[null]);
			}

			foreach ($groupedTypes as $types)
			{
				$intersection = array_intersect_key($types, $attributes);

				if (count($intersection) > 1)
				{
					array_shift($intersection);

					foreach ($intersection as $name => $type)
					{
						unset($attributes[$name]);
					}
				}
			}

			// save to database

			$snapshot = self::getSnapshot($attributes);

			$query = array(
				'limit'  => 1,
				'select' => array('ID'),
				'filter' => array('=SNAPSHOT' => $snapshot),
			);

			if ($row = ContextTable::getList($query)->fetch())
			{
				$id = (int) $row['ID'];
			}
			elseif (Option::get('conversion', 'CONTEXT_TABLE') != 'locked') // TODO remove if
			{
				try
				{
					$result = ContextTable::add(array('SNAPSHOT' => $snapshot));

					if ($result->isSuccess())
					{
						$id = $result->getId();

						foreach ($attributes as $name => $value)
						{
							// TODO resetContext if not success and return null!!!
							$result = ContextAttributeTable::add(array(
								'CONTEXT_ID' => $id,
								'NAME'       => $name,
								'VALUE'      => (string) $value, // can be null!
							));
						}
					}
					else
					{
						throw new DB\SqlQueryException();
					}
				}
				catch (DB\SqlQueryException $e)
				{
					if ($row = ContextTable::getList($query)->fetch())
					{
						$id = (int) $row['ID'];
					}
				}
			}
		}
	}

	static private function getSnapshot(array $attributes)
	{
		$keys = array();

		foreach ($attributes as $name => $value)
		{
			$keys []= $name.':'.$value;
		}

		sort($keys);

		$string = implode(';', $keys);

		return md5($string).md5(strrev($string));
	}
}