Browse Source
now right
now right
git-svn-id: svn+ssh://code.netmonsters.ru/svn/majestic/trunk@4 4cb57b5f-5bbd-dd11-951b-001d605cbbc5master
akulikov
16 years ago
12 changed files with 912 additions and 0 deletions
-
101Action.class.php
-
58Cache.class.php
-
40DBConnector.class.php
-
55Decorator.class.php
-
64Env.class.php
-
35Load.class.php
-
57MJException.class.php
-
186Model.class.php
-
27PageController.class.php
-
106Router.class.php
-
93Sublimer.class.php
-
90User.class.php
@ -0,0 +1,101 @@ |
|||
<?php |
|||
/** |
|||
* Рутовый класс для любого действия. |
|||
* Описывает основной функционал для работы с классами действий. |
|||
* |
|||
*/ |
|||
abstract class Action |
|||
{ |
|||
public $template; //шаблон действия
|
|||
public $template_dir = '.'; //путь к шаблону действия
|
|||
public $class; //имя дочернего класса
|
|||
|
|||
protected $templater; //шаблонизатор
|
|||
|
|||
public function __construct() |
|||
{ |
|||
$this->class = get_class($this); |
|||
$this->template = substr($this->class, 0, -strlen(ACTION_POSTFIX)); |
|||
|
|||
if (CACHE_ENABLE && ($cache_name = $this->getCacheKey()) !== false) { |
|||
$cache = new Cache($this->class.'_'.$cache_name, $this->getCacheTime()); |
|||
if ($cache->isCached()) { |
|||
$this->restore($cache->load()); |
|||
} else { |
|||
$this->init(); |
|||
$cache->save($this->store()); |
|||
} |
|||
} else { |
|||
$this->init(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Выдает результат действия. |
|||
* |
|||
* @return string |
|||
*/ |
|||
public function display() |
|||
{ |
|||
$this->templater = Load::templater(ACTION_TPL_PATH.'/'.$this->template_dir); |
|||
$this->prepare(); |
|||
return $this->templater->fetch($this->template.'.tpl'); |
|||
} |
|||
|
|||
/** |
|||
* Инициализация данных действия. |
|||
* Тут должна быть ВСЯ работа с установкой данных, |
|||
* дабы потом они нормально закешировались. |
|||
* Этот метод НЕ исполняется при срабатывании кеша. |
|||
* |
|||
*/ |
|||
abstract protected function init(); |
|||
|
|||
/** |
|||
* Подготовка данных для шаблона. |
|||
* Этот метод выполняется ВСЕГДА |
|||
*/ |
|||
protected function prepare() {} |
|||
|
|||
/** |
|||
* Возвращает имя файла для кеширования |
|||
* Переопределяется в доченрих классах. |
|||
* |
|||
* @return false/string - имя файла кеша либо false если кеш запрещен |
|||
*/ |
|||
protected function getCacheKey() |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* Возвращает время жизни кеша в секундах |
|||
* При отрицательном значении кеш вечен. |
|||
* Переопределяется в доченрих классах. |
|||
* |
|||
* @return false/integer - время жизни кеша либо false если кеш запрещен |
|||
*/ |
|||
protected function getCacheTime() |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
/** |
|||
* Выдает строку для кеширования. |
|||
*/ |
|||
protected function store() |
|||
{ |
|||
return serialize(get_object_vars($this)); |
|||
} |
|||
|
|||
/** |
|||
* Разбирает строку кеша, созданную методом store |
|||
*/ |
|||
protected function restore($data) |
|||
{ |
|||
foreach(unserialize($data) as $key => $val) { |
|||
$this->$key = $val; |
|||
} |
|||
} |
|||
} |
|||
?>
|
@ -0,0 +1,58 @@ |
|||
<?php |
|||
/** |
|||
* Класс кеша. |
|||
* Отвечает за киширование результатов выполнения действий. |
|||
* |
|||
*/ |
|||
final class Cache |
|||
{ |
|||
private $cache_file; |
|||
private $cache_time; |
|||
|
|||
function __construct($cache_name, $cache_time) |
|||
{ |
|||
$this->cache_time = (int) $cache_time; |
|||
$this->cache_file = CACHE_PATH.'/'.$cache_name; |
|||
} |
|||
|
|||
/** |
|||
* Сохраняет кэш в файл |
|||
* |
|||
* @return boolean - сохранил или нет |
|||
*/ |
|||
function save($data) |
|||
{ |
|||
if ($this->cache_time != 0) { |
|||
return (bool) file_put_contents($this->cache_file, $data); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* Достает кэш из файла |
|||
* |
|||
* @return string - содержимое кеша |
|||
*/ |
|||
function load() |
|||
{ |
|||
return file_get_contents($this->cache_file); |
|||
} |
|||
|
|||
/** |
|||
* Проверяет, закешированы ли данные с таким именем |
|||
* |
|||
* @return boolean - закеширован или нет |
|||
*/ |
|||
function isCached() |
|||
{ |
|||
if (! file_exists($this->cache_file)) { |
|||
return false; |
|||
} |
|||
if ($this->cache_time > 0 && $this->cache_time + filemtime($this->cache_file) < TIME_NOW) { |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
?>
|
@ -0,0 +1,40 @@ |
|||
<?php |
|||
/** |
|||
* Класс базы данных. |
|||
* Возвращает идентификатор соединения |
|||
* |
|||
*/ |
|||
class DBConnector |
|||
{ |
|||
static private $handlers = array(); |
|||
static public $queries = array(); |
|||
|
|||
/** |
|||
* Получение соединения. |
|||
* Если соединение с такими параметрами уже есть - новое не создается. |
|||
* |
|||
* @param array $db_settings - массив настроек |
|||
* @return resource - идентификатор соединения |
|||
*/ |
|||
static function getConnect($db_settings) |
|||
{ |
|||
$handler_name = self::getConnectionName($db_settings); |
|||
|
|||
if (isset(self::$handlers[$handler_name])) { |
|||
return self::$handlers[$handler_name]; |
|||
} |
|||
|
|||
if (!$handler = @mysqli_connect($db_settings['host'], $db_settings['user'], $db_settings['password'], $db_settings['database'])) { |
|||
throw new MJException('Can\'t connect to DB '.mysqli_connect_error(), 2); |
|||
} |
|||
|
|||
mysqli_query($handler, "SET NAMES 'utf8'"); //cheat!!!
|
|||
return self::$handlers[$handler_name] = $handler; |
|||
} |
|||
|
|||
static function getConnectionName($db_settings) |
|||
{ |
|||
return $db_settings['host'].'-'.$db_settings['database']; |
|||
} |
|||
} |
|||
?>
|
@ -0,0 +1,55 @@ |
|||
<?php |
|||
/** |
|||
* Родительский класс для всех декораторов. Содержит основной функционал. |
|||
* |
|||
*/ |
|||
abstract class Decorator |
|||
{ |
|||
protected $layout = false; |
|||
protected $action = false; |
|||
protected $action_name = 'Action'; |
|||
|
|||
protected $templater = false; |
|||
|
|||
function __construct() |
|||
{ |
|||
if (!$this->layout) { |
|||
throw new MJException('$layout not set in '.get_class($this)); |
|||
} |
|||
$this->templater = Load::templater(); |
|||
} |
|||
|
|||
/** |
|||
* Основной метод вывода |
|||
* |
|||
*/ |
|||
function display(Action $action) |
|||
{ |
|||
$this->action = $action; |
|||
$this->templater->assign($this->action_name, $this->action->display(), $this->layout); |
|||
|
|||
$this->exec(); |
|||
|
|||
$this->templater->setPath(WRAPPERS_TPL_PATH); |
|||
return $this->templater->fetch($this->layout); |
|||
} |
|||
|
|||
/** |
|||
* Добавить данные на вывод |
|||
* |
|||
* @param string $var_name - имя переменной, в которую будет осуществлен вывод |
|||
* @param Action $action - действие |
|||
* @param Decorator $decorator - декоратор, в котором должно выполнится действие. |
|||
*/ |
|||
function addOutput($var_name, Action $action, Decorator $decorator = null) |
|||
{ |
|||
$this->templater->assign($var_name, $decorator ? $decorator->display($action) : $action->display(), $this->layout); |
|||
} |
|||
|
|||
/** |
|||
* Основной метод для дочерних декораторов |
|||
* |
|||
*/ |
|||
abstract function exec(); |
|||
} |
|||
?>
|
@ -0,0 +1,64 @@ |
|||
<?php |
|||
/** |
|||
* Класс для работы с переменными окружения. |
|||
* |
|||
*/ |
|||
|
|||
final class Env |
|||
{ |
|||
static public $params = array(); |
|||
|
|||
static function Get($var, $default = false) |
|||
{ |
|||
return isset($_GET[$var]) ? $_GET[$var] : $default; |
|||
} |
|||
|
|||
static function Post($var, $default = false) |
|||
{ |
|||
return isset($_POST[$var]) ? $_POST[$var] : $default; |
|||
} |
|||
|
|||
static function Server($var, $default = false) |
|||
{ |
|||
return isset($_SERVER[$var]) ? $_SERVER[$var] : $default; |
|||
} |
|||
|
|||
static function Session($var, $default = false) |
|||
{ |
|||
return isset($_SESSION[$var]) ? $_SESSION[$var] : $default; |
|||
} |
|||
|
|||
static function getCookie($var, $default = false) |
|||
{ |
|||
return isset($_COOKIE[$var]) ? $_COOKIE[$var] : $default; |
|||
} |
|||
|
|||
static function setCookie($var, $value, $time = 0, $path = '/') |
|||
{ |
|||
return setcookie($var, $value, $time, $path); |
|||
} |
|||
|
|||
static function getParam($var, $default = false) |
|||
{ |
|||
return isset(self::$params[$var]) ? self::$params[$var] : $default; |
|||
} |
|||
|
|||
static function setParam($var, $val) |
|||
{ |
|||
self::$params[$var] = $val; |
|||
} |
|||
|
|||
static function setParams($params=array()) |
|||
{ |
|||
self::$params = self::$params + $params; |
|||
} |
|||
|
|||
static function parseTimer($time) |
|||
{ |
|||
$hours = intval($time / 3600); |
|||
$minutes = intval($time/60 - $hours*60); |
|||
|
|||
return sprintf('%02d:%02d:%02d', $hours, $minutes, $time - $hours*3600 - $minutes*60); |
|||
} |
|||
} |
|||
?>
|
@ -0,0 +1,35 @@ |
|||
<?php |
|||
|
|||
class Load |
|||
{ |
|||
static $models = array(); |
|||
static $templater = false; |
|||
static $router = false; |
|||
|
|||
static function model($model_name) |
|||
{ |
|||
if (isset(self::$models[$model_name])) { |
|||
return self::$models[$model_name]; |
|||
} |
|||
|
|||
$class_name = $model_name.MODEL_POSTFIX; |
|||
return self::$models[$model_name] = new $class_name; |
|||
} |
|||
|
|||
static function templater($path = '') |
|||
{ |
|||
if (self::$templater) { |
|||
if ($path) { |
|||
self::$templater->setPath($path); |
|||
} |
|||
return self::$templater; |
|||
} |
|||
return self::$templater = new Sublimer($path); |
|||
} |
|||
|
|||
static function router() |
|||
{ |
|||
return self::$router ? self::$router : self::$router = new Router; |
|||
} |
|||
} |
|||
?>
|
@ -0,0 +1,57 @@ |
|||
<?php |
|||
/** |
|||
* Обработчик эксепшенов |
|||
*/ |
|||
class MJException extends Exception |
|||
{ |
|||
private $line_range = 6; |
|||
|
|||
public function terminate() |
|||
{ |
|||
if (!DEBUG_ENABLE) { |
|||
return "Sorry, server temporary unavaible"; |
|||
} |
|||
|
|||
$return = "<b>MJ Error:</b> "; |
|||
$return .= str_replace("\n", "<br/>\n", $this->getMessage())."<br>\n"; |
|||
|
|||
$trace = $this->getTrace(); |
|||
|
|||
$file = reset($trace); |
|||
|
|||
//смещение в трейсе, указаное при вызове эксепшена (2й параметр). Нужно для более инофрмативного вывода
|
|||
if ($shift = abs($this->getCode())) { |
|||
while($shift--) { |
|||
$file = next($trace); |
|||
} |
|||
} |
|||
|
|||
if ($fp = fopen($file['file'], 'r')) { |
|||
$error_line = $file['line']; |
|||
$start = $error_line - $this->line_range; |
|||
$end = $error_line + $this->line_range; |
|||
$i = 1; |
|||
$return .= "<pre style=\"background-color:#e4e4e4\">"; |
|||
while ($line = fgets($fp, 4096) and $i<=$end) { |
|||
$line = htmlspecialchars($line); |
|||
if ($i >= $start && $i <= $end) { |
|||
if ($i == $error_line) $return .= '<div style="background-color:#cccccc">'.$i.' '.$line.'</div>'; |
|||
else $return .= $i.' '.$line; |
|||
} |
|||
$i++; |
|||
} |
|||
$return .= "</pre>"; |
|||
fclose($fp); |
|||
} |
|||
|
|||
$return .= '<table border="1" cellpadding="2" cellspacing="0"> <caption><b>Backtrace</b></caption>'; |
|||
$return .= "\n<tr><td><b>".$this->getFile().'</b></td><td><b>'.$this->getLine().'</b></td></tr>'; |
|||
foreach($trace as $row) { |
|||
if (isset($row['file'])) { //throwing exception from __call method will not return file and line
|
|||
$return .= "\n<tr".($file['file'] == $row['file'] ? ' style="background-color:#ffcccc"': '')."><td>".$row['file'].'</td><td>'.$row['line'].'</td></tr>'; |
|||
} |
|||
} |
|||
return $return . '</table>'; |
|||
} |
|||
} |
|||
?>
|
@ -0,0 +1,186 @@ |
|||
<?php |
|||
/** |
|||
* Класс модели данных |
|||
* |
|||
*/ |
|||
abstract class Model |
|||
{ |
|||
private $handler; |
|||
|
|||
protected $table = false; |
|||
protected $primary_key = 'id'; |
|||
|
|||
function __construct() |
|||
{ |
|||
$this->handler = DBConnector::getConnect(Env::getParam('db_settings')); |
|||
} |
|||
|
|||
/** |
|||
* Выполняет запрос и возвращает сырой результат |
|||
* |
|||
* @param string $sql |
|||
* @return resource |
|||
*/ |
|||
function exec($sql) |
|||
{ |
|||
$time = microtime(true); |
|||
$res = mysqli_query($this->handler, $sql); |
|||
if (mysqli_errno($this->handler)) { |
|||
throw new MJException("<b>Query Error:</b>\n".$sql."\n<b>Error:</b>\n".mysqli_error($this->handler), 1); |
|||
} |
|||
|
|||
if (DEBUG_ENABLE) { |
|||
DBConnector::$queries[] = $sql.'; ('.round((microtime(true)-$time)*1000, 1).'ms)'; |
|||
} |
|||
|
|||
return $res; |
|||
} |
|||
|
|||
/** |
|||
* Выполняет запрос и возвращает объект результата |
|||
* |
|||
* @param string $sql |
|||
* @return object |
|||
*/ |
|||
function query($sql) |
|||
{ |
|||
$res = $this->exec($sql); |
|||
|
|||
switch (strtolower(substr($sql, 0, 6))) { |
|||
case 'select': |
|||
return new ModelSelectResult($res); |
|||
case 'insert': |
|||
return new ModelInsertResult($this->handler); |
|||
default: |
|||
return new ModelChangeResult($this->handler); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Экранирует строку |
|||
* |
|||
* @param string $data - строка для экранирования |
|||
* @return string |
|||
*/ |
|||
function escape($data) |
|||
{ |
|||
return mysqli_real_escape_string($this->handler, $data); |
|||
} |
|||
|
|||
//////////////////////////
|
|||
function update($id, $data) |
|||
{ |
|||
$sql = ''; |
|||
foreach ($data as $key => $val) { |
|||
$sql .= $key."='".$this->escape($val)."', "; |
|||
} |
|||
return $this->query('UPDATE '.$this->table.' SET '.rtrim($sql, ', ').' WHERE '.$this->primary_key.'='.(int) $id); |
|||
} |
|||
|
|||
function insert($data, $postfix = '') |
|||
{ |
|||
$sql = ''; |
|||
foreach ($data as $key => $val) { |
|||
$sql .= $key.'="'.$this->escape($val).'", '; |
|||
} |
|||
return $this->query('INSERT '.$this->table.' SET '.rtrim($sql, ', ').' '.$postfix); |
|||
} |
|||
|
|||
function delete($id) |
|||
{ |
|||
return $this->query('DELETE FROM '.$this->table.' WHERE '.$this->primary_key.'='.(int) $id); |
|||
} |
|||
|
|||
function get($id) |
|||
{ |
|||
return $this->query('SELECT * FROM '.$this->table.' WHERE '.$this->primary_key.'='.(int) $id); |
|||
} |
|||
|
|||
function getList($limit = false, $sort = 'ASC') |
|||
{ |
|||
return $this->query('SELECT * FROM '.$this->table.' ORDER BY '.$this->primary_key.' '.($sort == 'ASC' ? 'ASC' : 'DESC').($limit === false ? ' LIMIT '.(int) $limit : '')); |
|||
} |
|||
} |
|||
|
|||
class ModelResult |
|||
{ |
|||
function __call($name, $args) |
|||
{ |
|||
throw new MJException('Call undeclared method "'.$name.'" in "'.get_class($this).'" class', -1); |
|||
} |
|||
} |
|||
|
|||
class ModelSelectResult extends ModelResult |
|||
{ |
|||
public $result; |
|||
|
|||
function __construct($res) |
|||
{ |
|||
$this->result = $res; |
|||
} |
|||
|
|||
function fetch() |
|||
{ |
|||
return mysqli_fetch_object($this->result); |
|||
} |
|||
|
|||
function fetchField($field, $default = false) |
|||
{ |
|||
$row = $this->fetch(); |
|||
return isset($row->$field) ? $row->$field : $default; |
|||
} |
|||
|
|||
function fetchAll() |
|||
{ |
|||
$array = array(); |
|||
while ($row = mysqli_fetch_object($this->result)) { |
|||
$array[] = $row; |
|||
} |
|||
return $array; |
|||
} |
|||
|
|||
function count() |
|||
{ |
|||
return mysqli_num_rows($this->result); |
|||
} |
|||
|
|||
function free() |
|||
{ |
|||
mysqli_free_result($this->result); |
|||
} |
|||
|
|||
function __destruct() { |
|||
$this->free(); |
|||
} |
|||
} |
|||
|
|||
class ModelChangeResult extends ModelResult |
|||
{ |
|||
public $affected; |
|||
|
|||
function __construct($resource) |
|||
{ |
|||
$this->affected = mysql_affected_rows($resource); |
|||
} |
|||
|
|||
function count() |
|||
{ |
|||
return $this->affected; |
|||
} |
|||
} |
|||
|
|||
class ModelInsertResult extends ModelResult |
|||
{ |
|||
public $id; |
|||
|
|||
function __construct($resource) |
|||
{ |
|||
$this->id = mysqli_insert_id($resource); |
|||
} |
|||
|
|||
function getId() |
|||
{ |
|||
return $this->id; |
|||
} |
|||
} |
|||
?>
|
@ -0,0 +1,27 @@ |
|||
<?php |
|||
|
|||
final class PageController |
|||
{ |
|||
|
|||
/** |
|||
* Вывод в браузер всего сайта. |
|||
* |
|||
*/ |
|||
public function display() |
|||
{ |
|||
try { |
|||
$this->route = Load::router()->proccess(MJ_PATH); |
|||
$decorator = new $this->route->decorator; |
|||
return $decorator->display(new $this->route->action); |
|||
} catch (MJException $e) { |
|||
return $e->terminate(); |
|||
} catch (Exception $e) { |
|||
$decorator_name = DEFAULT_DECORATOR; |
|||
$action_name = DEFAULT_ACTION; |
|||
|
|||
$decorator = new $decorator_name; |
|||
return $decorator->display(new $action_name($e->getMessage())); |
|||
} |
|||
} |
|||
} |
|||
?>
|
@ -0,0 +1,106 @@ |
|||
<?php |
|||
|
|||
/** |
|||
* Класс для работы с роутерами |
|||
* |
|||
*/ |
|||
final class Router |
|||
{ |
|||
protected $routes = array(); |
|||
|
|||
/** |
|||
* Добавить роутер |
|||
* |
|||
* @param string $name - имя роутера |
|||
* @param string $path - путь |
|||
* @param string $action - имя действия |
|||
* @param array $params - массив параметров |
|||
*/ |
|||
function add($name, $path, $action, $params = array()) |
|||
{ |
|||
$this->routes[$name] = new Route($path, $action, $params); |
|||
} |
|||
|
|||
/** |
|||
* Установить декоратор для роута (действия), отличный от стандартного |
|||
* |
|||
* @param string $name - имя роута (действия) |
|||
* @param string $decorator - имя декоратора |
|||
*/ |
|||
function setDecorator($name, $decorator) |
|||
{ |
|||
if (isset($this->routes[$name])) { |
|||
$this->routes[$name]->decorator = $decorator.DECORATOR_POSTFIX; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Найти роутер соответствующий заданному пути |
|||
* |
|||
* @param stirng $path - путь |
|||
* @return Route - роутер |
|||
*/ |
|||
function proccess($path) |
|||
{ |
|||
$path = explode('/', $path); |
|||
|
|||
foreach ($this->routes as $name => $route) { |
|||
if ($route->match($path)) { |
|||
$route->action .= ACTION_POSTFIX; |
|||
Env::setParams($route->params); |
|||
return $route; |
|||
} |
|||
} |
|||
throw new Exception(E_404); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Роутер |
|||
* |
|||
*/ |
|||
final class Route |
|||
{ |
|||
const URL_VARIABLE = '&'; |
|||
|
|||
protected $path; |
|||
|
|||
public $decorator = DEFAULT_DECORATOR; |
|||
public $action; |
|||
public $params; |
|||
|
|||
function __construct($path, $action, $params=array()) |
|||
{ |
|||
$this->path = $path; |
|||
$this->action = $action; |
|||
$this->params = $params; |
|||
} |
|||
|
|||
/** |
|||
* Проверяет соответствие роутера и пути |
|||
* |
|||
* @param string $path - путь для сравнения |
|||
* @return boolean - соответствует или нет |
|||
*/ |
|||
function match($path_arr) |
|||
{ |
|||
$parts = explode('/', $this->path); |
|||
$cnt = count($parts); |
|||
if (end($parts) == self::URL_VARIABLE) { |
|||
$cnt--; |
|||
} elseif ($cnt != count($path_arr)) { |
|||
return false; |
|||
} |
|||
|
|||
for ($i=0; $i<$cnt; $i++) { |
|||
if (substr($parts[$i], 0, 1) == self::URL_VARIABLE) { |
|||
$this->params[substr($parts[$i], 1)] = $path_arr[$i]; |
|||
} elseif ($parts[$i] != $path_arr[$i]) { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
?>
|
@ -0,0 +1,93 @@ |
|||
<?php |
|||
/** |
|||
* Простейший шаблонизатор. |
|||
* Зато быстрый. |
|||
* |
|||
*/ |
|||
|
|||
final class Sublimer |
|||
{ |
|||
const GLOBAL_KEY = 0; |
|||
|
|||
public $vars = array(); |
|||
public $path = ''; |
|||
public $template = ''; |
|||
|
|||
protected $head_array = array(); |
|||
|
|||
/** |
|||
* Конструктор |
|||
* |
|||
* @param string $path - путь до шаблонов |
|||
*/ |
|||
public function __construct($path = '') |
|||
{ |
|||
$this->setPath($path); |
|||
$this->vars[self::GLOBAL_KEY] = array(); |
|||
} |
|||
|
|||
/** |
|||
* Присвоить переменную только |
|||
* |
|||
* @param string $name - имя переменной |
|||
* @param mixed $value - значение переменной |
|||
* @param string $template - шаблон, если не указан, то переменная глобальная |
|||
*/ |
|||
public function assign($name, $value, $template = self::GLOBAL_KEY) |
|||
{ |
|||
$this->vars[$template][$name] = $value; |
|||
} |
|||
|
|||
/** |
|||
* Очистить стек переменных |
|||
* @param boolean $with_local - включая локальные переменные |
|||
*/ |
|||
public function clear($template = self::GLOBAL_KEY) |
|||
{ |
|||
$this->vars[$template] = array(); |
|||
} |
|||
|
|||
/** |
|||
* Обработать шаблон |
|||
* |
|||
* @param string $template - относительный путь до шаблона |
|||
* @return string - обработанное содержимое шаблона |
|||
*/ |
|||
public function fetch($template) |
|||
{ |
|||
$this->template = $template; //дабы экстракт не перезатер нам переменную. Это важно! $this то он не перезатрет :)
|
|||
extract($this->vars[self::GLOBAL_KEY]); |
|||
if (isset($this->vars[$this->template])) { |
|||
extract($this->vars[$this->template], EXTR_OVERWRITE); |
|||
} |
|||
ob_start(); |
|||
if (!(include $this->path.'/'.$this->template) == 'OK') { |
|||
throw new MJException('Template '.$this->path.'/'.$this->template.' not found'); |
|||
} |
|||
return ob_get_clean(); |
|||
} |
|||
|
|||
/** |
|||
* Установать путь до шаблонов |
|||
* |
|||
* @param string $path - путь до шаблонов |
|||
*/ |
|||
public function setPath($path) |
|||
{ |
|||
$this->path = $path; |
|||
} |
|||
|
|||
//Функции для вызова из шаблонов.
|
|||
|
|||
protected function addHead($str) |
|||
{ |
|||
$this->head_array[] = $str; |
|||
} |
|||
|
|||
protected function getHead() |
|||
{ |
|||
return $this->head_array; |
|||
} |
|||
} |
|||
|
|||
?>
|
@ -0,0 +1,90 @@ |
|||
<?php |
|||
/** |
|||
* Класс пользователя |
|||
* |
|||
*/ |
|||
class User |
|||
{ |
|||
static private $user = false; |
|||
|
|||
static function login($login, $password) |
|||
{ |
|||
if (empty($login)) { |
|||
return false; |
|||
} |
|||
|
|||
if (! self::$user = self::getByLogin($login) ) { |
|||
return false; |
|||
} |
|||
|
|||
if (self::$user->password != md5($password)) { |
|||
return false; |
|||
} |
|||
|
|||
self::setSession(); |
|||
return true; |
|||
} |
|||
|
|||
static function logout() |
|||
{ |
|||
Env::setCookie(session_name(), '', 0); |
|||
Env::setCookie('login', '', 0); |
|||
Env::setCookie('login_hash', '', 0); |
|||
if (session_id()) { |
|||
session_destroy(); |
|||
} |
|||
} |
|||
|
|||
static function process() |
|||
{ |
|||
if (Env::getCookie(session_name())) { //есть сессия
|
|||
session_start(); |
|||
} elseif (Env::getCookie('login') && Env::getCookie('login_hash')) { |
|||
self::remember(); |
|||
} |
|||
} |
|||
|
|||
static function setSession() |
|||
{ |
|||
Env::setCookie('login', self::$user->login, TIME_NOW + LOGIN_COOKIE_TTL); |
|||
Env::setCookie('login_hash', self::getHash(), TIME_NOW + LOGIN_COOKIE_TTL); |
|||
|
|||
session_start(); |
|||
|
|||
$_SESSION['user'] = self::$user; |
|||
} |
|||
|
|||
static function remember() |
|||
{ |
|||
if (! self::$user = self::getByLogin(Env::getCookie('login'))) { |
|||
self::logout(); |
|||
} |
|||
|
|||
if (Env::getCookie('login_hash') == self::getHash()) { |
|||
self::setSession(); |
|||
} else { |
|||
self::logout(); |
|||
} |
|||
} |
|||
|
|||
static function getHash() |
|||
{ |
|||
return md5(self::$user->id.'hckrz'.self::$user->login.'mst'.self::$user->password.'dai'); |
|||
} |
|||
|
|||
static function getInfo() |
|||
{ |
|||
return Env::Session('user', self::$user); |
|||
} |
|||
|
|||
static function isGuest() |
|||
{ |
|||
return ! (bool) Env::Session('user'); |
|||
} |
|||
|
|||
static function getByLogin($login) |
|||
{ |
|||
return Load::model('UserData')->getByLogin($login); |
|||
} |
|||
} |
|||
?>
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue