View file vkclone-0.0.1/protected/components/ConsoleCommand.php

File size: 7.52Kb
<?php
/**
 * This is a base class for console command
 */
class ConsoleCommand extends CConsoleCommand {

	const LOG_FILE_MASK = 'yiic_%d-%02d-%02d_%02d-%02d_%s-%s.log';

	/**
	 * A curl_* resource
	 */
	private $curlResource;

	/**
	 * Running profilers
	 */
	private $profilers = array();

	/**
	 * Selected action
	 */
	private $_action;
	/**
	 * Cli args
	 */
	private $_args;

	/**
	 * Инициализация
	 */
	public function init() {
		parent::init();

		mb_internal_encoding('utf-8');
		ignore_user_abort(true);
		set_time_limit(0);

		Yii::app()->setImport($this->import());
	}

	/**
	 * Установка импорта классов
	 */
	public function import() {
		return array();
	}

	/**
	 * Деструктор.
	 * Закрывает curl ресурс
	 */
	public function __destruct() {
		if (is_resource($this->curlResource))
			curl_close($this->curlResource);
	}

	/**
	 * Закончить выполнение скрипта выводом ошибки
	 * @param string $message Сообщение ошибки
	 * @param mixed Переменные для вывода через var_dump
	 */
	public function terminate($message) {
		echo '[error] '.$message.PHP_EOL;
		$args = func_get_args();
		array_shift($args);
		// if (!empty($args))
		// 	call_user_func_array('var_dump', $args);

		// create log dump
		$file = Yii::getPathOfAlias('logs').'/'.sprintf(self::LOG_FILE_MASK, date('Y'), date('m'), date('d'), date('H'), date('i'), $this->name, $this->_action);

		file_put_contents($file, 'Log created at '.date('r').PHP_EOL);
		file_put_contents($file, 'Message: '.$message.PHP_EOL, FILE_APPEND);
		$dump = null;
		foreach ($args as $i => $arg) {
			$dump .= 'Arg #'.$i.': '.var_export($arg, true).PHP_EOL;
		}
		file_put_contents($file, $dump.PHP_EOL, FILE_APPEND);
		echo 'Log saved to file '.$file.PHP_EOL;


		Yii::app()->end(1);
	}

	/**
	 * Saves action and args
	 */
	public function beforeAction($action, $args) {
		if (parent::beforeAction($action, $args)) {
			$this->_action = $action;
			$this->_args = $args;
			return true;
		}
		return false;
	}

	/**
	 * Отправить GET-запрос.
	 * При получении пустого результата (CURLE_GOT_NOTHING) выполнит запрос ещё раз.
	 * @param string $url
	 * @param array $config Массив для curl_setopt_array()
	 */
	public function getUrlContents($url, array $config = array()) {
		// echo '[debug] retrieving url: '.$url.PHP_EOL;
		$ch = $this->getCurlResource();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HEADER, 0);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

		curl_setopt_array($ch, $this->curlOptions());
		curl_setopt_array($ch, $config);

		$result = curl_exec($ch);
		if ($result === false) {
			$error = curl_error($ch);
			$errno = curl_errno($ch);
			if ($errno == CURLE_GOT_NOTHING)
				return $this->getUrlContents($url);
			else
				throw new RuntimeException('Curl error ('.$errno.') "'.$error.'"');
		}
		return $result;
	}

	/**
	 * Отправить POST-запрос с полями.
	 * @param string $url
	 * @param array $data Массив полей POST-запроса
	 * @param array $config Массив для curl_setopt_array()
	 */
	public function performPostRequest($url, array $data = array(), array $config = array()) {
		// echo '[debug] performing post request: '.$url.PHP_EOL;
		$ch = $this->getCurlResource();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HEADER, 0);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_POST, true);
		curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));

		curl_setopt_array($ch, $this->curlOptions());
		curl_setopt_array($ch, $config);

		$result = curl_exec($ch);
		if ($result === false) {
			$error = curl_error($ch);
			$errno = curl_errno($ch);
			throw new RuntimeException('Curl error ('.$errno.') "'.$error.'"');
		}
		return $result;
	}

	/**
	 * Перекодировать текст cp1251->utf-8
	 */
	public function convertToCp($string) {
		return mb_convert_encoding($string, 'cp1251', 'utf-8');
	}

	/**
	 * Перекодировать текст utf-8->cp1251
	 */
	public function convertToUnicode($string) {
		return mb_convert_encoding($string, 'utf-8', 'cp1251');
	}

	/**
	 * Старт профайлинга
	 * @return integer Номер рабочего профайлера
	 */
	public function beginProfile() {
		return array_push($this->profilers, microtime(true));
	}

	/**
	 * Закончить профайлинг и вывести затраченное время
	 * @param integer $n Номер профайлера
	 * @param string $title Строка, поясняющая выполненную работу
	 */
	public function endProfile($n, $title) {
		if (!isset($this->profilers[$n-1]))
			$this->terminate('Invalid profiler number!', $n);
		$time = microtime(true) - $this->profilers[$n-1];
		echo '[profiling] '.$title.":\t".round($time, 3).PHP_EOL;
	}

	/**
	 * Запрашивает подтверждение
	 * @param string $message Сообщение
	 * @param char $default Выбираемый по умолчанию вариант (y/n)
	 * @return boolean Согласился ли пользователь на подтверждение
	 */
	public function requestConfirm($message, $default = 'y') {
		$this->resetInputBuffer();

		$options = array('y' => true, 'n' => false);

		$default = (in_array($default, array_keys($options)) ? $default : 'y');

		$print_option = function ($option) use ($default) { return $option == $default ? strtoupper($option) : $option; };

		echo '[confirm] '.$message.' ['.$print_option('y').'/'.$print_option('n').']: ';

		stream_set_blocking(STDIN, 1);
		$line = strtolower(fgets(STDIN));
		$alternate_option = ($default == 'y' ? 'n' : 'y');
		if (substr($line, 0, 1) == $alternate_option)
			return $options[$alternate_option];
		else
			return $options[$default];

	}

	/**
	 * Запрашивает выбора из нескольких вариантов.
	 * Запрос будет идти до тех пор, пока пользователь не выберет один из варинатов.
	 * @param string $message Сообщение
	 * @param string[] $items Список вариантов
	 * @param string $default Выбираемый по умолчанию
	 * @return string Выбранный вариант
	 */
	public function requestSelection($message, array $items, $default = null) {
		$this->resetInputBuffer();

		echo '[select] '.$message.' ['.implode(',', $items).']: ';

		stream_set_blocking(STDIN, 1);
		$selected = trim(fgets(STDIN));

		if (in_array($selected, $items))
			return $selected;
		elseif ($default !== null)
			return $default;
		else
			return $this->requestSelection($message, $items);

	}

	/**
	 * Вывести отладочную информацию
	 */
	public function debug($string) {
		echo '[trace] '.$string.PHP_EOL;
	}

	/**
	 * Decodes html entities
	 */
	public function decodeHtmlEntities($string) {
		return html_entity_decode($string, ENT_QUOTES, 'UTF-8');
	}

	/**
	 * Очищает буффер stdin
	 */
	private function resetInputBuffer() {
		stream_set_blocking(STDIN, 0);
		while (fgets(STDIN) !== false);
	}

	/**
	 * Список опций, которые будут добавлены к curl
	 */
	protected function curlOptions() {
		return array();
	}

	/**
	 * Получение curl-ресурса
	 * @return resource
	 */
	private function getCurlResource() {
		if ($this->curlResource === null)
			$this->curlResource = curl_init();
		return $this->curlResource;
	}

}