118 Commits

Author SHA1 Message Date
d8031c497b 10_ballov-1452 10_ballov-174 Параметр возврата нового заполненногоq из запроса собственного экземпляра в SqlModel::fetch(). 2020-04-09 21:41:44 +03:00
984e9aa716 * make majestic models as orm-objects (only on single fetch record)
10_ballov-1431 Авторизация и вывод 3-й цены на мобильной версии зеленого моря
2020-03-27 21:39:45 +03:00
89ececaef2 Fix GeneralException namespace used in DbDriver 2020-01-10 00:16:20 +03:00
bb2d713ab3 count fix 2018-04-20 13:24:30 +03:00
e475484f5a ArraybleInterface - Arrayble 2016-01-25 08:52:48 +03:00
5f6a454e6a toArray in SqlResultCollection 2015-12-25 06:51:24 +03:00
aa9ac8dfe8 SqlCriteria - изменен расчет кол-ва записей при использовании GROUP BY
(In this thread: http://www.cyberforum.ru/mysql/thread681915.html
I have solution for my problem - USE COUNT(DISTINCT pid))
2015-03-19 17:04:46 +03:00
d9573958bd Исправление SqlCriteria::count() 2015-01-30 23:52:16 +03:00
d5a2da7cbf Correct count in SqlCriteria (fix1) 2015-01-30 23:38:09 +03:00
388673d856 Correct count in SqlCriteria 2015-01-30 23:30:22 +03:00
f954f79250 Оптимизация запроса на получения кол-ва записей SqlModel::count
MIRSPORTA-604 Исправление ошибок mysql
2015-01-27 17:43:23 +03:00
823a7af927 whereJoin - разрешено использовать без value 2014-12-10 11:56:42 +03:00
66d342272d Merge branch 'sql_criteria' into namespace
Conflicts:
	Model/SqlResultProvider.php
2014-11-11 13:44:08 +03:00
b6e002f5a8 Исправление ошибки в SqlCriteria.count() - дублирующееся COUNT(COUNT( * во внутреннем sql-запросе 2014-09-29 15:59:55 +04:00
bccd018530 Исправление ошибки в SqlCriteria.count() для запросов в которых есть свой индивидуальный select и groupby (fix1) 2014-09-27 17:05:33 +04:00
67f47b882b Исправление ошибки в SqlCriteria.count() для запросов в которых есть свой индивидуальный select и groupby 2014-09-27 17:00:46 +04:00
b7ff8ab3fc Исправление ошибки в SqlCriteria.count() 2014-09-26 18:44:35 +04:00
b4c3d89020 Correct SqlCriteria.count 2014-08-13 17:59:49 +04:00
9e359e0c25 Add assoc method into SqlResultCollection 2014-08-12 14:47:47 +04:00
776859b3c8 fix count method with saving original sql expression 2014-08-05 13:09:48 +04:00
acec4a521e Merge branch 'namespace' of dimti.ru:majestic into namespace 2014-07-30 21:31:52 +04:00
28efb6c675 fix erro in Form 2014-07-30 21:31:34 +04:00
383396b96d SqlCriteria - count - use $select parameter for preventions error with duplicate fields 2014-07-30 20:01:57 +04:00
d3f367d990 SqlResultProvider fetchField - check for empty result 2014-07-28 15:38:11 +04:00
b7fcfcf476 fix SqlCriteria count 2014-07-28 12:06:47 +04:00
2a98f9b0d7 Correct detect count records in SQlCriteria with use group by 2014-07-28 11:50:27 +04:00
15ea37109d Merge branch 'namespace' of dimti.ru:majestic into namespace 2014-07-28 09:28:00 +04:00
d42074b620 prepend notice error on session_start 2014-07-28 09:27:32 +04:00
0f8c0df4bc Merge branch 'namespace' of dimti.ru:majestic into namespace 2014-07-23 18:49:01 +04:00
b710a63dc7 App::abort(404) if route not found 2014-07-23 18:47:50 +04:00
9c58757641 Cache to namespace 2014-07-21 15:58:15 +04:00
1922886c2f Merge branch 'namespace' of dimti.ru:majestic into namespace 2014-07-03 19:50:13 +04:00
8c57655124 Remove error handler from FrontController 2014-07-03 19:49:43 +04:00
5b7a10e099 Merge branch 'namespace' of dimti.ru:majestic into namespace 2014-07-03 15:59:38 +04:00
b85c96c80e redis-doc hset. hget 2014-07-03 15:59:00 +04:00
60fdc48b2b fix - property_exists вместо isset 2014-06-19 21:45:02 +04:00
61be1700ee Отключение инициализации ErrorHandler 2014-06-19 19:17:28 +04:00
0057d6ff7c namesape fix 2014-06-06 20:03:51 +04:00
0dde2ccb59 Correct CliController for user namespace. Turn off error handler. 2014-06-04 22:30:31 +04:00
37c6dab160 Merge branch 'namespace' of dimti.ru:majestic into namespace 2014-06-04 21:57:29 +04:00
3709fb2a74 Correct namespace in Valdiators. Add namespace Mail. 2014-06-04 21:57:19 +04:00
c9b38314b5 Merge remote-tracking branch 'origin/sql_criteria' into namespace 2014-06-03 22:15:44 +04:00
52de52a17a Fix count 2014-06-03 20:06:56 +04:00
d710b19fed Correct use criteria with use count and join. 2014-06-03 19:56:30 +04:00
1ba341b064 Add namespace. 2014-06-02 18:58:49 +04:00
aec1a60985 Commit with composer.json 2014-05-27 17:56:46 +04:00
c62620593f Add vendor dir to autload. 2014-05-19 21:34:20 +04:00
e8e266a101 Merge branch 'sql_criteria' of dimti.ru:majestic into sql_criteria 2014-05-15 17:47:23 +04:00
ff148f2f95 SqlDbDriver - cancel identifier quotu for symbol "*" 2014-05-15 17:47:07 +04:00
906ffe07a8 Add identify quotes into table in SqlModel.find 2014-05-08 19:12:09 +04:00
cabb17b3c4 Merge branch 'sql_criteria' of dimti.ru:majestic into sql_criteria 2014-04-29 19:48:08 +04:00
3b390d968b Обработка массива term в условии where и строк в том числе. 2014-04-29 19:46:09 +04:00
0b0dc61960 Merge branch 'sql_criteria' of dimti.ru:majestic into sql_criteria 2014-04-25 20:17:15 +04:00
3a560dfe6f Correct PHP-Doc in FrontController for get PHPView. Add some methods into PHPView autocompletion interface (PHP-Doc). 2014-04-25 20:16:48 +04:00
d1c8ecf850 Modifie SqlCriteria.count() - force to use custom sql_expression. 2014-04-10 15:30:09 +04:00
d3b79e594f Use placeholders for table names in join operations. Correct use count with use join connections. 2014-03-14 18:50:51 +04:00
5f9c295c01 DIGITEC-314 Ошибка скрипта импорта
Создан интерфейс для классов SqlResultProvider и SqlResultCollection. В последний добавлены недостающие метода
2014-03-13 12:39:44 +04:00
6b0bf4058e DIGITEC-312 поиск на мобильной версии. зависание
Correct PHP-Doc
2014-03-11 15:48:02 +04:00
2cb51015e6 Fix in SqlResultProvider.getKeys(). 2014-03-11 15:44:20 +04:00
3272d7a903 Add SqlCriteria.join(). Refactoring SqlResultCollection (add SqlResultCollection). 2014-03-06 15:26:59 +04:00
740bd6b7f3 Modify CliController for opportunity to extend this class. 2014-03-05 19:11:11 +04:00
a090d52676 DIGITEC-222 - Автофиллинговые параметры должны иметь постоянный идентификатор
Исправление в SqlCriteria в методе select
2014-01-30 12:48:07 +04:00
94addf4ca9 Correct SqlResultProvider::fetchField() to work with empty results. 2013-12-24 10:00:51 +04:00
7486ab5cf1 Add MySQLiStatement::getMysqliResult() 2013-12-19 15:26:00 +04:00
8b17a8f911 MEBLOG-39 - Вывод наименование каталога 2013-11-21 12:26:09 +04:00
153d6fa20a Correct ordering params in SqlCriteria::order() 2013-11-18 18:47:14 +04:00
049999dfbd Merge branch 'sql_criteria' of dimti.ru:majestic into sql_criteria 2013-10-29 16:42:38 +04:00
4878b32641 Add group by support in sql criteria. 2013-10-29 16:42:33 +04:00
253b303084 Merge branch 'sql_criteria' of dimti.ru:majestic into sql_criteria 2013-10-23 11:57:34 +04:00
1ea6c5acdd Применение функции trim в методе SqlCriteria.select() 2013-10-23 11:54:27 +04:00
d019ae2450 Merge remote-tracking branch 'origin/extended_classes' into sql_criteria 2013-10-22 11:02:24 +04:00
8311fa1c26 Merge branch 'extended_classes' of dimti.ru:majestic into extended_classes 2013-10-21 15:51:34 +04:00
645ffd9ed1 Add support symlink into Autoload. 2013-10-21 15:51:24 +04:00
5d7162480a Добавлен метод whereNot - повтор для whereNotIn 2013-10-20 13:37:38 +04:00
3263af5e18 Add method SqlCriteria.whereNotIn(). 2013-10-17 21:23:32 +04:00
40e049c93e Корректировка в методе SqlCriteria.select(). 2013-10-10 15:28:41 +04:00
ff76d8fa1d Add into MsgViewHelper.getType() and use_as_html protected var. 2013-10-10 11:32:32 +04:00
559d779576 Update placeholder regular expression SqlDbDriver.quoteIdentifier(). 2013-10-09 08:59:54 +04:00
6890827f17 Fix in MySQLiStatement.mapPlaceholders() Use strictly placeholder names started with A-z symbol. 2013-10-09 08:35:15 +04:00
9a881f6560 Extend SqlCriteria::select() - use array or string for setting multiple fields of one call that method. 2013-10-09 07:07:34 +04:00
d1cf95b82c Merge branch 'extended_classes' into sql_criteria 2013-09-26 13:22:49 +04:00
3f6b2adefd SqlDbDriver quote identifier - add checking for string as placeholder. 2013-09-26 10:46:30 +04:00
e06ddba773 Correct call fetchAll in SqlModel.find(). 2013-09-26 10:45:46 +04:00
0fc1884c93 Extend Action.redirect() (add new param "permanently" for set header 301 Moved permanently). 2013-09-23 17:22:35 +04:00
9625b1e7a4 Extend MsgViewHelper. Add MsgViewHelper.getTypeToClass() 2013-09-23 13:41:04 +04:00
9ab3bfc0da Add TODO in SqlResultProvider. 2013-09-20 22:13:02 +04:00
dff9c0b2af Refactoring SqlCriteria, SqlModel. Add SqlResultProvider.fetchField(). 2013-09-20 22:11:54 +04:00
72c38e641d Refactoring assoc use in SqlResultProvider. Write SqlCriteria.find() method. 2013-09-19 12:54:10 +04:00
ba88ac5229 Merge branch 'extended_classes' into sql_criteria 2013-09-19 12:36:58 +04:00
ab01d0a41f Refactoring. Add SqlResultProvider. Add TODO in SqlDbDriver.whereExpr(). 2013-09-19 10:05:00 +04:00
2cb56ad228 Refactoring. Fix errors. Add SqlModel.assoc*() methods. 2013-09-17 18:42:04 +04:00
732b1ca8a5 Refactoring SqlModel.find() add SqlModel.criteria(). Add critera data keys as constants in SqlModel. 2013-09-17 14:57:56 +04:00
c890d082aa Add SqlCriteria class. Add SqlModel.find() with use SqlCriteria. 2013-09-17 09:51:20 +04:00
a51545268d Add CliLogger.generateOutString() for extend this class. 2013-09-16 11:28:09 +04:00
4b31df52c3 Add trait`s support to AutoloadBuilder. 2013-09-12 12:08:12 +04:00
f9de8ee3bc Merge branch 'feature_new_validators' into extended_classes 2013-09-10 18:05:45 +04:00
625752ced7 Modified EmailValidator add links to rfc specifications. 2013-09-10 17:05:14 +04:00
0ac9f3c5e8 Merge branch 'redis-doc' into extended_classes 2013-09-10 17:04:02 +04:00
7fd2961737 sInter 2013-09-10 17:03:22 +04:00
3e30e59e0b lRange, rPush, lTrim 2013-09-10 17:02:32 +04:00
a029cc3c57 sAdd, sCard, sSize, sMembers, sGetMembers, sContains, sIsMember, sRem, sRemove 2013-09-10 16:59:42 +04:00
5dd81b24fc Modified PHP-Doc for CliController::execute(). 2013-09-10 16:56:22 +04:00
8113986276 Add to ErrorHTTPException support code 401. 2013-09-10 16:55:14 +04:00
10c68143cb Изменен FileLogger для возможности расширения класса 2013-09-10 16:43:23 +04:00
ef99a26635 Modife CliController. 2013-09-10 16:41:13 +04:00
8133695eae Add Env.Request(). 2013-09-10 16:40:33 +04:00
5b9eab1067 Merge remote-tracking branch 'origin/fix_error_log' into extended_classes 2013-09-10 16:40:13 +04:00
3b6ae39707 Added new validators without tests 2012-12-12 13:11:54 +04:00
163ac086b0 Merge branch 'fix_error_log' 2012-12-11 19:25:15 +04:00
126d97b020 Added exception name to log 2012-12-11 19:08:37 +04:00
a2cb6a405e Get rid of $this->template logic, switched to type of exception 2012-12-11 18:56:07 +04:00
fce43da00d Fixed test error for testDebugAutoload() with coverage 2012-12-11 18:45:48 +04:00
98324588b7 added test for Mongo::addCondition method 2012-12-11 18:39:26 +04:00
c525a09078 fixed AutoloadBuilderTest to pass without template app 2012-12-11 16:46:53 +04:00
748393f653 Fixed function name 2012-12-11 16:28:04 +04:00
5f47dab73e Use new logError in FrontController, tests 2012-12-11 15:42:17 +04:00
91b364d01a Separate function ErrorHandler::logError() and tests 2012-12-11 15:03:48 +04:00
d007f356c0 Remove duplicate lines from test 2012-11-22 16:41:32 +04:00
164 changed files with 1773 additions and 785 deletions

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\App;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -13,7 +13,7 @@ abstract class Action
protected $template; protected $template;
/** /**
* @var PHPView * @var \Majestic\View\PHPView
*/ */
protected $view; protected $view;
@ -26,7 +26,7 @@ abstract class Action
protected function extractParams() protected function extractParams()
{ {
foreach (Env::getParam() as $name => $value) { foreach (\Majestic\Env::getParam() as $name => $value) {
if (is_string($name)) { if (is_string($name)) {
$this->$name = $value; $this->$name = $value;
} }
@ -39,10 +39,14 @@ abstract class Action
* Redirect * Redirect
* *
* @param mixed $url * @param mixed $url
* @param bool $permanently
*/ */
protected function redirect($url = null) protected function redirect($url = null, $permanently = false)
{ {
header('Location: ' . (($url) ? $url : Env::getRequestUri())); if ($permanently) {
header('HTTP/1.1 301 Moved Permanently');
}
header('Location: ' . (($url) ? $url : \Majestic\Env::getRequestUri()));
exit(); exit();
} }
@ -50,7 +54,7 @@ abstract class Action
{ {
$class = get_class($this); $class = get_class($this);
$template = ($this->template) ? $this->template : substr($class, 0, -6 /*strlen('Action')*/); $template = ($this->template) ? $this->template : substr($class, 0, -6 /*strlen('Action')*/);
$dir = array_slice(explode('/', Load::getFilePath($class)), -2, 1); $dir = array_slice(explode('/', \Majestic\Load::getFilePath($class)), -2, 1);
return '/actions/' . array_pop($dir) . '/' . $template; return '/actions/' . array_pop($dir) . '/' . $template;
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\App;
/** /**
* AjaxAction * AjaxAction
* *

99
App/CliController.php Normal file
View File

@ -0,0 +1,99 @@
<?php namespace Majestic\App;
/**
* @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru
* @package Majestic
* @subpackage App
* @since 27.06.12
*
*/
/**
* @desc CliController (run cli_class, end profiler)
* @author Aleksandr Demidov
*/
class CliController
{
/**
* @var CliController
*/
protected static $instance;
protected $error_stream;
protected function __construct()
{
//\Majestic\Exception\ErrorHandler::init();
$this->error_stream = \Majestic\Config::get('ErrorStream', 'php://stderr');
}
/**
* Refuse cloning
* @codeCoverageIgnoreStart
*/
private function __clone()
{
}
/**
* @codeCoverageIgnoreEnd
*/
/**
* @static
* @return CliController
*/
public static function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new static();
}
return self::$instance;
}
/**
* @param iCli|string $cli
* @throws \ErrorException|\Majestic\Exception\GeneralException
*/
public function execute($cli)
{
try {
$this->run($cli);
}
catch (\Exception $e) {
$this->exception($e);
}
}
protected function run($cli)
{
if (is_string($cli)) {
if (!class_exists($cli)) {
throw new \Majestic\Exception\GeneralException('Action class "' . $cli . '" not found.');
}
$cli = new $cli;
}
if (!in_array('Majestic\App\iCli', class_implements($cli))) {
throw new \ErrorException('Runner "' . get_class($cli) . '" need implement of "iCli" interface.');
}
$cli->run();
if (\Majestic\Config::get('PROFILER')) {
$profile = \Majestic\Util\Profiler\Profiler::getInstance()->getCli();
if (\Majestic\Config::get('LOGGING')) {
\Majestic\Logger\Logger::getInstance()->log($profile);
} else {
echo $profile;
}
}
}
protected function exception($e)
{
$code = $e->getCode();
if ($e instanceof \ErrorException) {
$code = $e->getSeverity();
}
file_put_contents($this->error_stream, PHP_EOL . 'Error ' . '#' . $code . ': ' . $e->getMessage() . PHP_EOL, FILE_APPEND);
file_put_contents($this->error_stream, PHP_EOL . 'Stack trace: ' . PHP_EOL . $e->getTraceAsString() . PHP_EOL, FILE_APPEND);
}
}

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\App;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -11,7 +11,7 @@ class ErrorAction extends Action
{ {
/** /**
* @var ErrorException|ErrorHTTPException * @var \ErrorException|\Majestic\Exception\ErrorHTTPException
*/ */
public $exception; public $exception;
@ -25,11 +25,12 @@ class ErrorAction extends Action
protected function execute() protected function execute()
{ {
$this->template = 500; if ($this->exception instanceof \Majestic\Exception\Error404Exception) {
if ($this->exception instanceof Error404Exception) {
$this->template = 404; $this->template = 404;
} elseif ($this->exception instanceof ErrorHTTPException) { } elseif ($this->exception instanceof \Majestic\Exception\ErrorHTTPException) {
$this->template = 'HTTP'; $this->template = 'HTTP';
} else {
$this->template = 500;
} }
$this->logError(); $this->logError();
$this->sendHTTPCode(); $this->sendHTTPCode();
@ -50,42 +51,17 @@ class ErrorAction extends Action
protected function sendHttpCode() protected function sendHttpCode()
{ {
switch ($this->template) { if ($this->exception instanceof \Majestic\Exception\ErrorHTTPException) {
case 404: header($this->exception->getHTTPHeader());
case 'HTTP': } else {
header($this->exception->getHTTPHeader()); header('HTTP/1.0 500 Internal Server Error');
break;
default:
header('HTTP/1.0 500 Internal Server Error');
} }
} }
protected function logError() protected function logError()
{ {
if ($this->template == 500) { if (!$this->exception instanceof \Majestic\Exception\Error404Exception) {
$error = 0; \Majestic\Exception\ErrorHandler::logError($this->exception);
$ex = $this->exception;
if ($ex instanceof ErrorException) {
$error = $ex->getSeverity();
}
switch ($error) {
case E_NOTICE:
$error = 'Notice';
break;
case E_WARNING:
$error = 'Warning';
break;
case E_ERROR:
$error = 'Fatal Error';
break;
default:
$error = 'Unknown Error';
break;
}
$message = 'PHP ' . $error . ': ' . $ex->getMessage() . ' in ' . $ex->getFile()
. ' on line ' . $ex->getLine();
error_log($message);
} }
} }

137
App/FrontController.php Normal file
View File

@ -0,0 +1,137 @@
<?php namespace Majestic\App;
/**
* @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru
* @package Majestic
* @subpackage app
* @since 2010-02-24
*/
class FrontController
{
/**
* @var Router\Router
*/
protected $router;
/**
* @var string
*/
protected $view = '\Majestic\View\PHPView';
protected $base_url = '';
/**
* @var FrontController
*/
protected static $instance;
private function __construct()
{
// \Majestic\Exception\ErrorHandler::init();
$this->router = new Router\Router();
}
/**
* Refuse cloning
* @codeCoverageIgnoreStart
*/
private function __clone()
{
}
/**
* @codeCoverageIgnoreEnd
*/
/**
* @return FrontController
*/
static public function getInstance()
{
if (!isset(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
/**
* @param string $view
* @return FrontController
*/
public function setView($view)
{
$this->view = $view;
return $this;
}
/**
*
* @param null $view
* @return ..\View\PHPView
*/
public function getView($view = null)
{
$view = ($view) ? $view : $this->view;
return new $view(\Majestic\Config::get($view));
}
/**
* @param string $url
* @return FrontController
*/
public function setBaseUrl($url)
{
$this->base_url = rtrim($url, '/');
return $this;
}
public function getBaseUrl()
{
return $this->base_url;
}
/**
* @return Router\Router
*/
public function getRouter()
{
return $this->router;
}
public function execute()
{
$request = \Majestic\Env::getRequestUri(true);
$route = $this->getRouter()->route($request);
if (!$route) {
$message = 'Route for "' . $request . '" not found';
\App::abort(404, $message);
}
$action_class = $route->getAction();
if (!class_exists($action_class)) {
throw new \Majestic\Exception\GeneralException('Action class "' . $action_class . '" not found.');
}
$action = new $action_class();
$layout_class = $route->getLayout();
if (!class_exists($layout_class)) {
throw new \Majestic\Exception\GeneralException('Layout class "' . $layout_class . '" not found.');
}
/**
* @var \Majestic\Layout\Layout $layout
*/
$layout = new $layout_class();
$html = $layout->fetch($action);
if (\Majestic\Config::get('PROFILER')) {
if (is_subclass_of($action, 'AjaxAction')) {
\Majestic\Util\Profiler\Profiler::getInstance()->getJson();
} else {
$html = \Majestic\Util\Profiler\Profiler::getInstance()->end($html);
}
}
return $html;
}
}

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\App;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\App\Router;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\App\Router;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -48,7 +48,7 @@ class Router
if ($route->match($req)) { if ($route->match($req)) {
$this->route_name = $name; $this->route_name = $name;
$this->route = $route; $this->route = $route;
Env::setParams($route->getParams()); \Majestic\Env::setParams($route->getParams());
return $this->route; return $this->route;
} }
} }
@ -94,7 +94,7 @@ class Router
/** /**
* @param null|string $name * @param null|string $name
* @return Route * @return Route
* @throws ErrorException * @throws \ErrorException
*/ */
public function getRoute($name = null) public function getRoute($name = null)
{ {
@ -104,7 +104,7 @@ class Router
if ($this->routeIsExists($name)) { if ($this->routeIsExists($name)) {
return $this->getRouteByName($name); return $this->getRouteByName($name);
} else { } else {
throw new ErrorException('Unknown route name: "' . $name . '".'); throw new \ErrorException('Unknown route name: "' . $name . '".');
} }
} }
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\App;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\App;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

View File

@ -6,7 +6,7 @@
* @subpackage Cache * @subpackage Cache
* @since 2010-03-04 * @since 2010-03-04
*/ */
namespace Majestic\Core;
abstract class Cache abstract class Cache
{ {

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -7,6 +7,8 @@
* @since 2010-02-17 * @since 2010-02-17
*/ */
class Config extends Registry class Config extends Registry
{ {
@ -21,17 +23,17 @@ class Config extends Registry
} }
} }
class ConfigArray extends ArrayObject class ConfigArray extends \ArrayObject
{ {
public function __construct($array) public function __construct($array)
{ {
parent::__construct($array, ArrayObject::ARRAY_AS_PROPS); parent::__construct($array, \ArrayObject::ARRAY_AS_PROPS);
} }
public function offsetGet($index) public function offsetGet($index)
{ {
if (!$this->offsetExists($index)) { if (!$this->offsetExists($index)) {
throw new GeneralException('Configuration variable "' . $index . '" undefined'); throw new Exception\GeneralException('Configuration variable "' . $index . '" undefined');
} }
return parent::offsetGet($index); return parent::offsetGet($index);
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic;
/** /**
* Класс для работы с переменными окружения. * Класс для работы с переменными окружения.
* *
@ -23,7 +23,7 @@ class Env
list(self::$request[$trim_base], ) = explode('?', Env::Server('REQUEST_URI')); list(self::$request[$trim_base], ) = explode('?', Env::Server('REQUEST_URI'));
if ($trim_base) { if ($trim_base) {
// removes base url // removes base url
$base = FrontController::getInstance()->getBaseUrl(); $base = \Majestic\App\FrontController::getInstance()->getBaseUrl();
if (($length = strlen($base)) > 0 && strpos(self::$request[$trim_base], $base) === 0) { if (($length = strlen($base)) > 0 && strpos(self::$request[$trim_base], $base) === 0) {
self::$request[$trim_base] = (string) substr(self::$request[$trim_base], $length); self::$request[$trim_base] = (string) substr(self::$request[$trim_base], $length);
} }
@ -47,6 +47,14 @@ class Env
} }
return (isset($_POST[$key])) ? $_POST[$key] : $default; return (isset($_POST[$key])) ? $_POST[$key] : $default;
} }
static public function Request($key = null, $default = null)
{
if ($key === null) {
return $_REQUEST;
}
return (isset($_REQUEST[$key])) ? $_REQUEST[$key] : $default;
}
static public function Cookie($key = null, $default = false) static public function Cookie($key = null, $default = false)
{ {

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Exception;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -8,7 +8,7 @@
*/ */
class Error404Exception extends ErrorHTTPException { class Error404Exception extends ErrorHTTPException {
function __construct($message = '', $code = null, Exception $previous = NULL ) function __construct($message = '', $code = null, \Exception $previous = NULL )
{ {
parent::__construct($message, 404, $previous); parent::__construct($message, 404, $previous);
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Exception;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -15,6 +15,7 @@ class ErrorHTTPException extends GeneralException
{ {
$this->http_headers = array( $this->http_headers = array(
400 => 'HTTP/1.0 400 Bad Request', 400 => 'HTTP/1.0 400 Bad Request',
401 => 'HTTP/1.0 400 Access allowed only for registered users',
402 => 'HTTP/1.0 402 Payment Required', 402 => 'HTTP/1.0 402 Payment Required',
403 => 'HTTP/1.0 403 Forbidden', 403 => 'HTTP/1.0 403 Forbidden',
404 => 'HTTP/1.0 404 Not Found', 404 => 'HTTP/1.0 404 Not Found',

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Exception;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -12,7 +12,7 @@ class ErrorHandler
static public function init() static public function init()
{ {
set_error_handler(array('ErrorHandler', 'error_handler')); //set_error_handler(array('Majestic\Exception\ErrorHandler', 'error_handler'));
} }
static public function error_handler($errno, $errstr, $errfile, $errline) static public function error_handler($errno, $errstr, $errfile, $errline)
@ -22,11 +22,50 @@ class ErrorHandler
ob_end_clean(); ob_end_clean();
} }
if (error_reporting() !== 0) { if (error_reporting() !== 0) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline); throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
} }
return true; return true;
} }
static public function logError($exception)
{
$error = 0;
$exception_name = '';
if ($exception instanceof \ErrorException) {
$error = $exception->getSeverity();
} else {
$exception_name = get_class($exception) . ': ';
}
switch ($error) {
case E_NOTICE:
$error = 'Notice';
break;
case E_WARNING:
$error = 'Warning';
break;
case E_ERROR:
$error = 'Fatal Error';
break;
default:
$error = 'Unknown Error';
break;
}
$message = 'PHP ' . $error . ': ' . $exception_name . $exception->getMessage() . ' in ' . $exception->getFile() . ':' . $exception->getLine() . ' \nStack trace:\n' . $exception->getTraceAsString() . self::getHTTPErrorConditions();
// PHP Fatal error: Uncaught exception 'LogicException' in /www/test.tfs/face/htdocs/index.php:11\nStack trace:\n#0 {main}\n thrown in /www/test.tfs/face/htdocs/index.php on line 11, referer: http://test.tfs.manekeno.netmonsters.ru/news/create
error_log($message);
}
static public function getHTTPErrorConditions()
{
$text = null;
if (!is_null(\Majestic\Env::Server('REQUEST_METHOD')) && !is_null(\Majestic\Env::Server('REQUEST_URI'))) {
$text = ', URL: ' . \Majestic\Env::Server('REQUEST_METHOD') . ' ' . \Majestic\Env::Server('REQUEST_URI');
$text .= ', referrer: ' . \Majestic\Env::Server('HTTP_REFERER');
}
return $text;
}
static protected function getSource($file, $hiline) static protected function getSource($file, $hiline)
{ {
$code = array(); $code = array();
@ -70,7 +109,7 @@ class ErrorHandler
} }
/** /**
* @param Exception $exception * @param \Exception $exception
* @return string * @return string
*/ */
static public function showDebug($exception) static public function showDebug($exception)
@ -81,19 +120,19 @@ class ErrorHandler
} }
$class = get_class($exception); $class = get_class($exception);
$method = Env::Server('REQUEST_METHOD', ''); $method = \Majestic\Env::Server('REQUEST_METHOD', '');
$uri = Env::getRequestUri(); $uri = \Majestic\Env::getRequestUri();
$source = self::getSource($exception->getFile(), $exception->getLine()); $source = self::getSource($exception->getFile(), $exception->getLine());
$time = date('r', Env::Server('REQUEST_TIME', time())); $time = date('r', \Majestic\Env::Server('REQUEST_TIME', time()));
$trace = nl2br($exception->getTraceAsString()); $trace = nl2br($exception->getTraceAsString());
$get = self::wrapArray(Env::Get(), 'GET'); $get = self::wrapArray(\Majestic\Env::Get(), 'GET');
$post = self::wrapArray(Env::Post(), 'POST'); $post = self::wrapArray(\Majestic\Env::Post(), 'POST');
$session = self::wrapArray(Session::get(), 'SESSION'); $session = self::wrapArray(\Majestic\Session\Session::get(), 'SESSION');
$files = self::wrapArray(Env::Files(), 'FILES'); $files = self::wrapArray(\Majestic\Env::Files(), 'FILES');
$cookies = self::wrapArray(Env::Cookie(), 'COOKIE'); $cookies = self::wrapArray(\Majestic\Env::Cookie(), 'COOKIE');
$server = self::wrapArray(Env::Server(), 'SERVER'); $server = self::wrapArray(\Majestic\Env::Server(), 'SERVER');
$message = <<<EOD $message = <<<EOD
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Exception;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -7,4 +7,4 @@
* @since 2010-02-26 * @since 2010-02-26
*/ */
class GeneralException extends Exception {} class GeneralException extends \Exception {}

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Exception;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -9,4 +9,4 @@
* Exception from initializtion object * Exception from initializtion object
*/ */
class InitializationException extends Exception {} class InitializationException extends \Exception {}

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Form;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -47,7 +47,7 @@ abstract class Form
public function isValid($data) public function isValid($data)
{ {
if (!is_array($data)) { if (!is_array($data)) {
throw new InitializationException(__CLASS__ . '::' . __METHOD__ . ' expects an array'); throw new \Majestic\Exception\InitializationException(__CLASS__ . '::' . __METHOD__ . ' expects an array');
} }
foreach ($this->fields as $field_name => $field) { foreach ($this->fields as $field_name => $field) {
@ -148,7 +148,7 @@ abstract class Form
{ {
$data['messages'] = $this->getMessages(); $data['messages'] = $this->getMessages();
$data['values'] = $this->getSourceValues(); $data['values'] = $this->getSourceValues();
Session::set(get_class($this), $data); \Majestic\Session\Session::set(get_class($this), $data);
} }
abstract protected function init(); abstract protected function init();

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Form;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -93,7 +93,7 @@ class FormField
} }
/** /**
* @param string[]|iValidator[] $validators * @param string[]|\Majestic\Validator\iValidator[] $validators
* @return FormField * @return FormField
*/ */
public function addValidators($validators) public function addValidators($validators)
@ -105,19 +105,19 @@ class FormField
} }
/** /**
* @param string|iValidator $validator * @param string|\Majestic\Validator\iValidator $validator
* @return FormField * @return FormField
* @throws InitializationException * @throws \Majestic\Exception\InitializationException
*/ */
public function addValidator($validator) public function addValidator($validator)
{ {
if ($validator instanceof iValidator) { if ($validator instanceof \Majestic\Validator\iValidator) {
$name = get_class($validator); $name = get_class($validator);
} elseif (is_string($validator)) { } elseif (is_string($validator)) {
$name = $validator . 'Validator'; $name = $validator . 'Validator';
$validator = new $name(); $validator = new $name();
} else { } else {
throw new InitializationException('Invalid validator provided to addValidator; must be string or iValidator'); throw new \Majestic\Exception\InitializationException('Invalid validator provided to addValidator; must be string or iValidator');
} }
$this->validators[$name] = $validator; $this->validators[$name] = $validator;
return $this; return $this;
@ -139,7 +139,7 @@ class FormField
$name = $filter . 'Filter'; $name = $filter . 'Filter';
$filter = new $name(); $filter = new $name();
} else { } else {
throw new InitializationException('Invalid filter provided to addFilter; must be string or iFilter'); throw new \Majestic\Exception\InitializationException('Invalid filter provided to addFilter; must be string or iFilter');
} }
$this->filters[$name] = $filter; $this->filters[$name] = $filter;
return $this; return $this;
@ -192,7 +192,7 @@ class FormField
if (!$validator->isValid($val, $context)) { if (!$validator->isValid($val, $context)) {
$valid = false; $valid = false;
if (!$this->default_message) { if (!$this->default_message) {
throw new InitializationException('Define default message for array fields'); throw new \Majestic\Validator\InitializationException('Define default message for array fields');
} }
$this->message = $this->default_message; $this->message = $this->default_message;
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Form;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -16,10 +16,10 @@ class FormViewHelper extends ViewHelper
{ {
if ($this->data === null) { if ($this->data === null) {
if ($form == null) { if ($form == null) {
throw new InitializationException('Form name required for helper init'); throw new \Majestic\ExceptionInitializationException('Form name required for helper init');
} }
$this->data = Session::get($form, array()); $this->data = \Majestic\Session\Session::get($form, array());
Session::del($form); \Majestic\Session\Session::del($form);
} }
return $this; return $this;
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Layout;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -10,7 +10,7 @@
class ErrorLayout extends Layout class ErrorLayout extends Layout
{ {
/** /**
* @var GeneralException * @var \Majestic\ExceptionGeneralException
*/ */
protected $exception; protected $exception;
@ -19,9 +19,9 @@ class ErrorLayout extends Layout
} }
/** /**
* @param Exception $exception * @param \Exception $exception
*/ */
public function setException(Exception $exception) public function setException(\Exception $exception)
{ {
$this->exception = $exception; $this->exception = $exception;
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Layout;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -13,18 +13,18 @@ abstract class Layout
protected $template; protected $template;
/** /**
* @var PHPView * @var \Majestic\View\PHPView
*/ */
protected $view; protected $view;
public function __construct() public function __construct()
{ {
$this->view = FrontController::getInstance()->getView(); $this->view = \Majestic\App\FrontController::getInstance()->getView();
} }
/** /**
* @param string $name * @param string $name
* @param Action $action * @param \Majestic\App\Action $action
*/ */
protected function assign($name, $action) protected function assign($name, $action)
{ {
@ -34,7 +34,7 @@ abstract class Layout
/** /**
* @param string $name * @param string $name
* @param Action $action * @param \Majestic\App\Action $action
*/ */
protected function append($name, $action) protected function append($name, $action)
{ {
@ -44,7 +44,7 @@ abstract class Layout
/** /**
* @param string $name * @param string $name
* @param Action $action * @param \Majestic\App\Action $action
*/ */
protected function prepend($name, $action) protected function prepend($name, $action)
{ {
@ -55,7 +55,7 @@ abstract class Layout
/** /**
* Execute Action, insert action's result html into layout template and return Layout html * Execute Action, insert action's result html into layout template and return Layout html
* @param Action $action * @param \Majestic\App\Action $action
* @return string * @return string
*/ */
public function fetch($action) public function fetch($action)

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -16,6 +16,17 @@ class Load
static protected $exclude = array(); static protected $exclude = array();
static protected $builder = null;
/**
* @var \Composer\Autoload\ClassLoader
*/
static protected $class_loader;
static public function setClassLoader($class_loader) {
self::$class_loader = $class_loader;
}
/** /**
* Add exclude path for autoload. Should be called before setAutoloadFrom * Add exclude path for autoload. Should be called before setAutoloadFrom
* @static * @static
@ -24,12 +35,12 @@ class Load
*/ */
static public function setExclude($exclude = array()) static public function setExclude($exclude = array())
{ {
if(!is_array($exclude)) { if (!is_array($exclude)) {
$exclude = array($exclude); $exclude = array($exclude);
} }
self::$exclude = array_merge(self::$exclude, $exclude); self::$exclude = array_merge(self::$exclude, $exclude);
} }
static public function setAutoloadFrom($file) static public function setAutoloadFrom($file)
{ {
self::$file = $file; self::$file = $file;
@ -60,7 +71,11 @@ class Load
static public function getFilePath($class) static public function getFilePath($class)
{ {
return self::$autoload[$class]; if (self::$class_loader) {
return self::$class_loader->findFile($class);
} else {
return self::$autoload[$class];
}
} }
static protected function buildAutoload() static protected function buildAutoload()
@ -71,13 +86,16 @@ class Load
trigger_error('Can\'t create directory: "' . $dir . '"', E_USER_ERROR); trigger_error('Can\'t create directory: "' . $dir . '"', E_USER_ERROR);
} }
$scan = array(PATH . '/' . APP . '/src', PATH . '/lib'); $scan = array(PATH . '/' . APP . '/src', PATH . '/lib', PATH . '/vendor');
$exclude = array_merge(self::$exclude, array(PATH . '/.git', PATH . '/lib/core/tests', PATH . '/lib/core/.git')); $exclude = array_merge(self::$exclude, array(PATH . '/.git', PATH . '/lib/core/tests', PATH . '/lib/core/.git'));
require_once(PATH . '/lib/core/util/AutoloadBuilder.php');
$builder = new AutoloadBuilder(self::$file, $scan, $exclude); if (!self::$builder) {
$builder->build(); require_once(PATH . '/lib/core/util/AutoloadBuilder.php');
require_once(PATH . '/lib/core/util/AsciiSortedIterator.php');
self::$builder = new AutoloadBuilder(self::$file, $scan, $exclude);
}
self::$builder->build();
ignore_user_abort(false); ignore_user_abort(false);
} }
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Logger;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -14,8 +14,13 @@ class CliLogger extends Logger
{ {
// Заменяем окончания строк на их символы // Заменяем окончания строк на их символы
$message = str_replace(array("\r", "\n"), array('\r', '\n'), $message); $message = str_replace(array("\r", "\n"), array('\r', '\n'), $message);
$out = microtime(true) . " \t: " . $this->pid . trim($message) . PHP_EOL; $out = $this->generateOutString($message);
print($out); print($out);
} }
protected function generateOutString($message)
{
return microtime(true) . " \t: " . $this->pid . trim($message) . PHP_EOL;
}
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Logger;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -20,17 +20,22 @@ class FileLogger extends Logger
protected function __construct() protected function __construct()
{ {
$this->file_path = Config::get('Logger')->filepath; $this->file_path = \Majestic\Config::get('Logger')->filepath;
}
protected function generateOutString($message)
{
return microtime(true) . " \t: " . $this->pid . trim($message) . "\r\n";
} }
protected function concreteLog($message) protected function concreteLog($message)
{ {
$out = microtime(true) . " \t: " . $this->pid . trim($message) . "\r\n"; $out = $this->generateOutString($message);
if (!$this->handler) { if (!$this->handler) {
$this->handler = @fopen($this->file_path, "a"); $this->handler = @fopen($this->file_path, "a");
if (!$this->handler) { if (!$this->handler) {
throw new GeneralException('Could not open file ' . $this->file_path); throw new \Majestic\Exception\GeneralException('Could not open file ' . $this->file_path);
} }
} }
fwrite($this->handler, $out); fwrite($this->handler, $out);

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Logger;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -31,7 +31,7 @@ abstract class Logger
{ {
if (static::$_instance === null) { if (static::$_instance === null) {
//$class = get_called_class(); //$class = get_called_class();
$class = Config::get('Logger')->logger; $class = \Majestic\Config::get('Logger')->logger;
static::$_instance = new $class(); static::$_instance = new $class();
} }
return static::$_instance; return static::$_instance;
@ -43,7 +43,7 @@ abstract class Logger
*/ */
public function log($message) public function log($message)
{ {
if (Config::get('LOGGING')) { if (\Majestic\Config::get('LOGGING')) {
$this->concreteLog($message); $this->concreteLog($message);
} }
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Mail;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Model;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -29,23 +29,23 @@ class Db
* @param array $config Configuration array. * @param array $config Configuration array.
* *
* @return DbDriver * @return DbDriver
* @throws InitializationException * @throws \Majestic\Exception\InitializationException
*/ */
static public function connect($name = 'default', $config = null) static public function connect($name = 'default', $config = null)
{ {
if (!isset(self::$connections[$name])) { if (!isset(self::$connections[$name])) {
if (!$config) { if (!$config) {
if (!is_object(Config::get(__CLASS__))) { if (!is_object(\Majestic\Config::get(__CLASS__))) {
throw new InitializationException('Trying to get property of non-object'); throw new \Majestic\Exception\InitializationException('Trying to get property of non-object');
} }
$config = Config::get(__CLASS__)->$name; $config = \Majestic\Config::get(__CLASS__)->$name;
} }
if (!is_array($config)) { if (!is_array($config)) {
throw new InitializationException('Connection parameters must be an array'); throw new \Majestic\Exception\InitializationException('Connection parameters must be an array');
} }
$driver = 'MySQLiDriver'; $driver = '\Majestic\Model\MySQLiDriver';
if (isset($config['driver'])) { if (isset($config['driver'])) {
$driver = $config['driver']; $driver = $config['driver'];
unset($config['driver']); unset($config['driver']);
@ -54,7 +54,7 @@ class Db
$connection = new $driver($config); $connection = new $driver($config);
if (!$connection instanceof DbDriver) { if (!$connection instanceof DbDriver) {
throw new InitializationException('Database driver must extends DbDriver'); throw new \Majestic\Exception\InitializationException('Database driver must extends DbDriver');
} }
self::$connections[$name] = $connection; self::$connections[$name] = $connection;
} }

View File

@ -1,4 +1,6 @@
<?php <?php namespace Majestic\Model;
use Majestic\Exception\GeneralException;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Model;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Model;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Model;
/** /**
* Класс модели данных * Класс модели данных
@ -23,7 +23,7 @@ abstract class Model
/** /**
* Cache instance * Cache instance
* *
* @var Cache * @var \Cache
*/ */
protected $cache; protected $cache;
@ -94,12 +94,12 @@ abstract class Model
/* Cache workaround */ /* Cache workaround */
/** /**
* @return Cache * @return \Cache
*/ */
public function getCache() public function getCache()
{ {
if (!$this->cache) { if (!$this->cache) {
$this->cache = Cacher::get(Config::get(__CLASS__, 'MemcacheCache')); $this->cache = \Cacher::get(\Majestic\Config::get(__CLASS__, 'MemcacheCache'));
} }
return $this->cache; return $this->cache;
} }
@ -107,16 +107,16 @@ abstract class Model
/** /**
* @param string $name * @param string $name
* @param array $params * @param array $params
* @return CacheKey * @return \CacheKey
*/ */
protected function cacheKey($name, $params = array()) protected function cacheKey($name, $params = array())
{ {
$expire = (isset($this->cache_keys[$name])) ? ($this->cache_keys[$name] * 60) : 0; $expire = (isset($this->cache_keys[$name])) ? ($this->cache_keys[$name] * 60) : 0;
return new CacheKey($this->getCache(), $name, $params, $expire); return new \CacheKey($this->getCache(), $name, $params, $expire);
} }
/** /**
* @param CacheKey $cache * @param \CacheKey $cache
*/ */
protected function addCleanCache($cache) protected function addCleanCache($cache)
{ {
@ -152,21 +152,21 @@ abstract class Model
* @param string $data Request * @param string $data Request
* @param array $params Request parameters * @param array $params Request parameters
* @param string $field Requested field name * @param string $field Requested field name
* @param CacheKey $cache_key Key for caching in * @param \CacheKey $cache_key Key for caching in
*/ */
abstract protected function fetchField($data, $params = array(), $field, $cache_key = null); abstract protected function fetchField($data, $params = array(), $field, $cache_key = null);
/** /**
* @param string $data Request * @param string $data Request
* @param array $params Request parameters * @param array $params Request parameters
* @param CacheKey $cache_key Key for caching in * @param \CacheKey $cache_key Key for caching in
*/ */
abstract protected function fetch($data, $params = array(), $cache_key = null); abstract protected function fetch($data, $params = array(), $cache_key = null);
/** /**
* @param string $data * @param string $data
* @param array $params * @param array $params
* @param CacheKey $cache_key * @param \CacheKey $cache_key
*/ */
abstract protected function fetchAll($data, $params = array(), $cache_key = null); abstract protected function fetchAll($data, $params = array(), $cache_key = null);
} }

View File

@ -49,14 +49,14 @@ abstract class MongoDbCommand
* Execute Mongo command/query * Execute Mongo command/query
* *
* @return mixed * @return mixed
* @throws GeneralException * @throws \Majestic\Exception\GeneralException
*/ */
public function execute() public function execute()
{ {
if ($this->checkParams()) { if ($this->checkParams()) {
return $this->concreteExecute(); return $this->concreteExecute();
} else { } else {
throw new GeneralException(get_called_class() . ' error. Bind all required params first.'); throw new \Majestic\Exception\GeneralException(get_called_class() . ' error. Bind all required params first.');
} }
} }

View File

@ -159,7 +159,7 @@ abstract class MongoModel extends Model
/** /**
* @param array $params Parameters for find query * @param array $params Parameters for find query
* @return array Query result sort rules * @return array Query result sort rules
* @throws GeneralException * @throws \Majestic\Exception\GeneralException
* */ * */
private function getOrder($params = array()) private function getOrder($params = array())
{ {
@ -170,7 +170,7 @@ abstract class MongoModel extends Model
} elseif (is_array($params['order'])) { } elseif (is_array($params['order'])) {
$order = $params['order']; $order = $params['order'];
} else { } else {
throw new GeneralException('Wrong order parameter given to query.'); throw new \Majestic\Exception\GeneralException('Wrong order parameter given to query.');
} }
} }
return $order; return $order;
@ -179,7 +179,7 @@ abstract class MongoModel extends Model
/** /**
* @param array $params Parameters for find query * @param array $params Parameters for find query
* @return array Query result sort rules * @return array Query result sort rules
* @throws GeneralException * @throws \Majestic\Exception\GeneralException
* */ * */
private function getFields($params) private function getFields($params)
{ {
@ -196,7 +196,7 @@ abstract class MongoModel extends Model
$fields = $params['fields']; $fields = $params['fields'];
} }
} else { } else {
throw new GeneralException('Wrong fields parameter given to query.'); throw new \Majestic\Exception\GeneralException('Wrong fields parameter given to query.');
} }
} }
return $fields; return $fields;

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Model;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -8,7 +8,7 @@
*/ */
/** /**
* @property MySQLi $connection * @property \MySQLi $connection
*/ */
class MySQLiDriver extends SqlDbDriver class MySQLiDriver extends SqlDbDriver
{ {
@ -51,7 +51,7 @@ class MySQLiDriver extends SqlDbDriver
public function isConnected() public function isConnected()
{ {
return ($this->connection instanceof MySQLi); return ($this->connection instanceof \MySQLi);
} }
public function disconnect() public function disconnect()
@ -78,7 +78,7 @@ class MySQLiDriver extends SqlDbDriver
$port); $port);
// Connection errors check // Connection errors check
if (mysqli_connect_error()) { if (mysqli_connect_error()) {
throw new GeneralException(mysqli_connect_error(), mysqli_connect_errno()); throw new \Majestic\Exception\GeneralException(mysqli_connect_error(), mysqli_connect_errno());
} }
$charset = (!empty($this->config['charset'])) ? $this->config['charset'] : 'utf8'; $charset = (!empty($this->config['charset'])) ? $this->config['charset'] : 'utf8';

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Model;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -9,7 +9,7 @@
/** /**
* @property MySQLiDriver $driver * @property MySQLiDriver $driver
* @property MySQLi_Result $result * @property \MySQLi_Result $result
*/ */
class MySQLiStatement extends DbStatement class MySQLiStatement extends DbStatement
{ {
@ -21,24 +21,26 @@ class MySQLiStatement extends DbStatement
if ($this->map === null) { if ($this->map === null) {
$this->mapPlaceholders(); $this->mapPlaceholders();
} }
if (count($this->map) > 0) {
if ($this->map) {
if (!is_string($param) && !is_int($param)) { if (!is_string($param) && !is_int($param)) {
throw new GeneralException('Placeholder must be an integer or string'); throw new \Majestic\Exception\GeneralException('Placeholder must be an integer or string');
} }
if (is_object($value) && ! ($value instanceof DbExpr)) { if (is_object($value) && ! ($value instanceof DbExpr)) {
throw new GeneralException('Objects excepts DbExpr not allowed.'); throw new \Majestic\Exception\GeneralException('Objects excepts DbExpr not allowed.');
} }
if (isset($this->map[$param])) { if (isset($this->map[$param])) {
$this->params[$param] = &$value; $this->params[$param] = &$value;
return true; return true;
} }
} }
return false; return false;
} }
protected function mapPlaceholders() protected function mapPlaceholders()
{ {
$matches = array(); $matches = array();
if(preg_match_all('/(\?|:[A-z0-9_]+)/u', $this->request, $matches, PREG_OFFSET_CAPTURE)) { if(preg_match_all('/(\?|:[A-z][A-z0-9_]*+)/u', $this->request, $matches, PREG_OFFSET_CAPTURE)) {
$noname = 0; $noname = 0;
foreach ($matches[0] as $id=>$match) { foreach ($matches[0] as $id=>$match) {
$match[2] = $matches[1][$id][0]; $match[2] = $matches[1][$id][0];
@ -81,7 +83,7 @@ class MySQLiStatement extends DbStatement
* *
* @param mixed $style * @param mixed $style
* @return mixed * @return mixed
* @throws GeneralException * @throws \Majestic\Exception\GeneralException
*/ */
public function fetch($style = Db::FETCH_OBJ) public function fetch($style = Db::FETCH_OBJ)
{ {
@ -103,7 +105,7 @@ class MySQLiStatement extends DbStatement
$row = $this->result->fetch_array(MYSQLI_BOTH); $row = $this->result->fetch_array(MYSQLI_BOTH);
break; break;
default: default:
throw new GeneralException('Invalid fetch mode "' . $style . '" specified'); throw new \Majestic\Exception\GeneralException('Invalid fetch mode "' . $style . '" specified');
} }
return $row; return $row;
} }
@ -150,14 +152,19 @@ class MySQLiStatement extends DbStatement
return false; return false;
} }
public function getMysqliResult()
{
return $this->result;
}
protected function driverExecute($request) protected function driverExecute($request)
{ {
/** /**
* @var MySQLi * @var \MySQLi
*/ */
$mysqli = $this->driver->getConnection(); $mysqli = $this->driver->getConnection();
if (Config::get('PROFILER_DETAILS')) { if (\Majestic\Config::get('PROFILER_DETAILS')) {
$profiler = Profiler::getInstance()->profilerCommand('MySQL', $request); $profiler = \Majestic\Util\Profiler\Profiler::getInstance()->profilerCommand('MySQL', $request);
$result = $mysqli->query($request); $result = $mysqli->query($request);
$profiler->end(); $profiler->end();
} else { } else {
@ -165,9 +172,9 @@ class MySQLiStatement extends DbStatement
} }
if ($result === false) { if ($result === false) {
$message = $mysqli->error . "\nQuery: \"" . $request . '"'; $message = $mysqli->error . "\nQuery: \"" . $request . '"';
throw new GeneralException($message, $mysqli->errno); throw new \Majestic\Exception\GeneralException($message, $mysqli->errno);
} }
if ($result instanceof MySQLi_Result) { if ($result instanceof \MySQLi_Result) {
$this->result = $result; $this->result = $result;
} }
return true; return true;

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Model;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

277
Model/SqlCriteria.php Normal file
View File

@ -0,0 +1,277 @@
<?php namespace Majestic\Model;
class SqlCriteria
{
const JOIN_TYPE_DEFAULT = 100;
const JOIN_TYPE_LEFT = 101;
const JOIN_TYPE_RIGHT = 102;
const JOIN_TYPE_INNER = 103;
const JOIN_TYPE_OUTER = 104;
private static $join_reserved_keyword = array(
self::JOIN_TYPE_DEFAULT => 'JOIN',
self::JOIN_TYPE_LEFT => 'LEFT JOIN',
self::JOIN_TYPE_RIGHT => 'RIGHT JOIN',
self::JOIN_TYPE_INNER => 'INNER JOIN',
self::JOIN_TYPE_OUTER => 'OUTER JOIN',
);
private $select = array();
private $distinct = '';
private $where = array();
private $group_by = array();
private $order = array('sort' => array(), 'order' => array());
private $limit = '';
/**
* @var SqlModel
*/
private $model;
private $sql_expression;
private $sql_expression_params = array();
private $sql_join_expressions = array();
private $join_table_placeholder = array();
/**
* @param $model SqlModel
* @param $sql_expression string|null Sql expression with SELECT and FROM operators. If fetched, then SqlCriteria::select(), SqlCriteria::distinct() disabled for use.
* @param $sql_expression_params array additional params to be replaced in sql expression
*/
public function __construct($model, $sql_expression = null, $sql_expression_params = array())
{
$this->model = $model;
$this->sql_expression = $sql_expression;
$this->sql_expression_params = $sql_expression_params;
}
/**
* @return SqlResultProvider
*/
public function find()
{
$this->defineJoinExpressions();
return $this->model->find($this->select, $this->distinct, $this->where, $this->order, $this->limit, null, $this->group_by, $this->sql_expression, $this->sql_expression_params);
}
private function defineJoinExpressions($select = null)
{
if ($this->sql_join_expressions) {
if (!$this->sql_expression) {
$select = $this->model->getDb()->selectExpr($select ? : $this->select, $this->distinct);
$this->sql_expression = 'SELECT ' . $select . ' FROM :table';
}
$this->sql_expression .= ' ' . implode(' ', $this->sql_join_expressions);
$this->sql_join_expressions = null;
}
}
public function delete()
{
return $this->model->find('', '', $this->where, null, null, null, null, 'DELETE FROM :table', $this->sql_expression_params)->affectedRows();
}
//TODO: перенести определение sql_expression в модель
public function count($select = null)
{
$this->defineJoinExpressions($select);
$sql_expression_backup = $this->sql_expression;
$group_by_backup = $this->group_by;
$select_parent_query = 'COUNT(*) as count';
$default_select = '*';
if ($this->group_by) {
$default_select = 'DISTINCT ' . $this->group_by[0];
}
$this->group_by = [];
if (!$this->sql_expression) {
$this->sql_expression = 'SELECT COUNT(' . ($select ? $select : $default_select) . ') as count FROM :table';
$select_parent_query = 'x.count';
} else {
$this->sql_expression = preg_replace('#SELECT.+FROM#i', 'SELECT COUNT(' . ($select ? $select : $default_select) . ') as count FROM', $this->sql_expression);
}
$count = $this->model->count($select_parent_query, $this->where, null, $this->group_by, $this->sql_expression, $this->sql_expression_params)->fetchField('count');
$this->sql_expression = $sql_expression_backup;
$this->group_by = $group_by_backup;
return $count;
}
private function defineJoinTablePlaceholder($table_name)
{
if (!isset($this->join_table_placeholder[$table_name])) {
$this->join_table_placeholder[$table_name] = ':table' . (count($this->join_table_placeholder) + 1);
}
}
public function getTablePh($table_name)
{
$this->defineJoinTablePlaceholder($table_name);
return $this->join_table_placeholder[$table_name];
}
public function join($join_table_name, $join_field_name, $donor_table_name = null, $donor_field_name = null, $join_type = self::JOIN_TYPE_DEFAULT)
{
$donor_field_name = $donor_field_name ? : $join_field_name;
$donor_table_placeholder = $donor_table_name ? $this->getTablePh($donor_table_name) : ':table';
$join_table_placeholder = $this->getTablePh($join_table_name);
$this->sql_join_expressions[] = self::$join_reserved_keyword[$join_type]
. ' ' . $join_table_placeholder
. ' ON ' . $donor_table_placeholder . '.' . $donor_field_name . '='
. ' ' . $join_table_placeholder . '.' . $join_field_name;
if ($donor_table_name) {
$this->sql_expression_params[substr($donor_table_placeholder, 1)] = new DbExpr($this->model->identify($donor_table_name));
}
$this->sql_expression_params[substr($join_table_placeholder, 1)] = new DbExpr($this->model->identify($join_table_name));
return $this;
}
/**
* @param $cond string|array Condition with "?" placeholder @ex 'field=?' or 'field=1' or array('field=?' => 1', 'field=1')
* @param $value string|array|DbExpr|null Value. Array transformed to DbExpr(implode(',' Array)) All elements in the array mast be integer
* @return SqlCriteria
* @desc Allow multiple calls
*/
public function where($cond, $value = null)
{
if (is_null($value)) {
if (is_array($cond)) {
$this->where = $this->where + $cond;
} else {
$this->where[] = $cond;
}
} else {
$this->where[$cond] = $value;
}
return $this;
}
public function whereJoin($join_table_name, $cond, $value = null)
{
$join_table_placeholder = $this->getTablePh($join_table_name);
if (is_array($cond)) {
$cond_replace = array();
foreach ($cond as $key => $value) {
$cond_replace[$this->getCondWithTablePlaceholderIfNeed($join_table_placeholder, $key)] = $value;
}
} else {
$cond = $this->getCondWithTablePlaceholderIfNeed($join_table_placeholder, $cond);
}
return $this->where($cond, $value);
}
private function getCondWithTablePlaceholderIfNeed($table_placeholder, $cond)
{
if (!strstr('.', $cond)) {
$cond = $table_placeholder . '.' . $cond;
}
return $cond;
}
/**
* @param $field string
* @param $value array
* @return SqlCriteria
*/
public function whereIn($field, $value)
{
return $this->where($field . ' in ?', $value);
}
/**
* @param $field string
* @param $value array
* @return SqlCriteria
*/
public function whereNotIn($field, $value)
{
return $this->where($field . ' not in ?', $value);
}
/**
* @param $field string
* @param $value array
* @return SqlCriteria
* @deprecated
*/
public function whereNot($field, $value)
{
return $this->whereNotIn($field, $value);
}
public function groupBy($fields)
{
if (is_array($fields)) {
$this->group_by = $this->group_by + $fields;
} else {
$this->group_by[] = $fields;
}
return $this;
}
/**
* @param $field string Field @ex 'field'
* @param $order_desc bool Descendant sort direction
* @return SqlCriteria
* @desc Allow multiple calls
*/
public function order($field, $order_desc = false)
{
$this->order['sort'][] = $field;
if ($order_desc) {
$this->order['order'][$field] = 'desc';
}
return $this;
}
/**
* @param $offset int
* @param $limit int
* @return SqlCriteria
*/
public function limit($offset = 0, $limit)
{
if ($offset) {
$this->limit = (int) $offset . ',';
}
$this->limit .= (int) $limit;
return $this;
}
/**
* @param string|array $fields
* @param bool $convert_to_db_expression
* @ex SqlCriteria::select('field')
* @ex SqlCriteria->select(array('field1', 'field2'))
* @ex SqlCriteria->select('field1,field2')
* @return SqlCriteria
*/
public function select($fields, $convert_to_db_expression = false)
{
if (!is_array($fields)) {
$fields = explode(',', $fields);
}
$fields = array_map(function($item){return trim($item);},$fields);
if ($convert_to_db_expression) {
$fields = array_map(function($item){return new DbExpr($item);},$fields);
}
$this->select = array_merge($this->select,$fields);
return $this;
}
/**
* @param $field string|bool If true then distinct by *
* @return SqlCriteria
*/
public function distinct($field)
{
$this->distinct = $field;
return $this;
}
}

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Model;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -110,7 +110,9 @@ abstract class SqlDbDriver extends DbDriver
{ {
$ident = explode('.', $ident); $ident = explode('.', $ident);
foreach ($ident as &$segment) { foreach ($ident as &$segment) {
$segment = $this->identifier_quote . $segment . $this->identifier_quote; if (!preg_match('/^(\?|:[A-z][A-z0-9_]*+|\*)$/u', $segment)) {
$segment = $this->identifier_quote . $segment . $this->identifier_quote;
}
} }
return implode('.', $ident); return implode('.', $ident);
} }
@ -127,8 +129,9 @@ abstract class SqlDbDriver extends DbDriver
/** /**
* @param mixed $where * @param mixed $where
* @return string * @return string
* @throws \ErrorException
*/ */
protected function whereExpr($where) public function whereExpr($where)
{ {
if (empty($where)) { if (empty($where)) {
return $where; return $where;
@ -139,16 +142,88 @@ abstract class SqlDbDriver extends DbDriver
} }
foreach ($where as $cond => &$term) { foreach ($where as $cond => &$term) {
if (is_int($cond)) { if (is_int($cond)) {
if (is_int($term)) {
throw new \ErrorException('Condition in where expression as integer. ' . $term);
}
if ($term instanceof DbExpr) { if ($term instanceof DbExpr) {
$term = (string) $term; $term = (string) $term;
} }
} else { } else {
if (is_array($term)) {
foreach ($term as &$val) {
$val = $this->driverQuote($val);
}
$term = new DbExpr('(' . implode(',', $term) . ')');
}
$term = $this->quoteInto($cond, $term); $term = $this->quoteInto($cond, $term);
} }
} }
return implode(' AND ', $where); return implode(' AND ', $where);
} }
/**
* @param mixed $group_by
* @return string
* @throws \ErrorException
*/
public function groupByExpr($group_by)
{
if (empty($group_by)) {
return $group_by;
}
if (!is_array($group_by)) {
$group_by = array($group_by);
}
foreach ($group_by as &$term) {
if ($term instanceof DbExpr) {
$term = (string) $term;
} else {
$term = $this->quoteIdentifier($term);
}
}
return implode(',', $group_by);
}
/**
* @param $select array
* @param $distinct string|bool
* @return string
*/
public function selectExpr($select, $distinct = false)
{
if (empty($distinct) && empty($select)) {
return '*';
}
if (!is_array($select)) {
$select = array($select);
}
if ($distinct) {
$distinct = ((is_bool($distinct)) ? '*' : $this->quoteIdentifier($distinct));
array_unshift($select, new DbExpr('DISTINCT ' . $distinct));
}
foreach ($select as $field => &$term) {
if (is_int($field)) {
if ($term instanceof DbExpr) {
$term = (string) $term;
} else {
$term = $this->quoteIdentifier($term);
}
} else {
$term = $this->quoteIdentifier($field) . ' as ' . $this->quoteIdentifier($term);
}
}
return implode(',', $select);
}
public function limitExpr($limit)
{
if (empty($limit)) {
return $limit;
}
return implode(',',array_map(function($item){return intval($item);},explode(',',$limit)));
}
abstract protected function driverQuote($value); abstract protected function driverQuote($value);
abstract protected function driverBeginTransaction(); abstract protected function driverBeginTransaction();

268
Model/SqlModel.php Normal file
View File

@ -0,0 +1,268 @@
<?php namespace Majestic\Model;
/**
* Класс модели данных
*
* @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru
* @package Majestic
* @subpackage Model
* @since 2011-11-11
*/
/**
* @property SqlDbDriver $db
*/
abstract class SqlModel extends Model
{
/**
* @param string $ident
* @return string Quoted identifier.
*/
public function identify($ident)
{
return $this->db->quoteIdentifier($ident);
}
/**
* @param mixed $value
* @return string Quoted value.
*/
public function quote($value)
{
return $this->db->quote($value);
}
public function getDb()
{
return $this->db;
}
/**
* @param int $id
* @return object
*/
public function get($id)
{
$sql = 'SELECT * FROM :table WHERE :pk=?';
return $this->fetch($sql, $id);
}
/**
* @param array $data
* @param mixed $where
* @return int Number of affected rows
*/
public function update($data, $where)
{
if (is_int($where) || $where === (string)(int)$where) {
$where = $this->identify($this->key) . '=' . (int)$where;
}
return parent::update($data, $where);
}
/**
* @param int $id Int id
* @return int Number of affected rows
*/
public function delete($id)
{
$where = $this->identify($this->key) . '=' . (int)$id;
return $this->db->delete($this->table(), $where);
}
/**
* Creates order sql string
*
* @param array $params
* @param array $sortable
* @return string
*/
protected function order($params, $sortable = array('id'))
{
$sql = '';
if (isset($params['sort'])) {
if (!is_array($params['sort'])) {
if (isset($params['order'])) {
$params['order'] = array($params['sort'] => $params['order']);
}
$params['sort'] = array($params['sort']);
}
$order_list = array();
for ($i = 0; $i < count($params['sort']); $i++) {
$order = (isset($params['order'][$params['sort'][$i]]) && $params['order'][$params['sort'][$i]] == 'desc') ? 'DESC' : 'ASC';
if (in_array($params['sort'][$i], $sortable)) {
$order_list[] = $this->identify($params['sort'][$i]) . ' ' . $order;
}
}
if ($order_list) {
$sql = ' ORDER BY ' . implode(',', $order_list);
}
}
return $sql;
}
/**
* Searches using like
*
* @param array $params
* @param array $searchable
* @param string $table_prefix
* @return string
*/
protected function search($params, $searchable = array('id'), $table_prefix = '')
{
$sql = '';
if (isset($params['q']) && isset($params['qt']) && in_array($params['qt'], $searchable)) {
if ($table_prefix) {
$sql = $table_prefix . '.';
}
$sql .= $this->identify($params['qt']) . ' LIKE ' . $this->quote('%' . $params['q'] . '%');
}
return $sql;
}
/**
* This method appends to params table and primary key.
* So they can be accessed through `:table` and `:pk` placeholders.
*
* @param string $sql
* @param array $params
* @return DbStatement
*/
protected function query($sql, $params = array())
{
if (!is_array($params)) {
$params = array($params);
}
$params = array(
'table' => new DbExpr($this->identify($this->table())),
'pk' => new DbExpr($this->identify($this->key)),
) + $params;
return $this->db->query($sql, $params);
}
/**
* @param string $data Request
* @param array $params Request parameters
* @param string $field Requested field name
* @param CacheKey $cache_key Key for caching in
* @return mixed
*/
protected function fetchField($data, $params = array(), $field, $cache_key = null)
{
if (!$cache_key || !$result = $cache_key->get()) {
$result = $this->query($data, $params)->fetchField($field);
if ($cache_key) {
$cache_key->set($result);
}
}
return $result;
}
/**
* @param string $data Request
* @param array $params Request parameters
* @param CacheKey $cache_key Key for caching in
* @param bool $returnNewInstance Return the instance of this filled from query
* @return mixed
*/
protected function fetch($data, $params = array(), $cache_key = null, $returnFilledInstance = true)
{
if (!$cache_key || !$result = $cache_key->get()) {
$result = $this->query($data, $params)->fetch();
if ($cache_key) {
$cache_key->set($result);
}
}
if ($result && $returnFilledInstance) {
$instance = new $this;
foreach (get_object_vars($result) as $key => $value) {
if ($key == 'table') {
$key = 'table_field';
}
$instance->$key = $value;
}
return $instance;
}
return $result;
}
/**
* @param string $data
* @param array $params
* @param CacheKey $cache_key
* @return array
*/
protected function fetchAll($data, $params = array(), $cache_key = null)
{
if (!$cache_key || !$result = $cache_key->get()) {
$result = $this->query($data, $params)->fetchAll();
if ($cache_key) {
$cache_key->set($result);
}
}
return $result;
}
/**
* @param $select array
* @param $distinct string|bool
* @param $where array @ex array('field=?' => $value, 'field=1')
* @param $order array @ex array('sort' => array('field1', 'field2'), 'order' => array('field2' => 'desc'))
* @param $limit string @ex '30' or '30,30'
* @param $heaving TODO
* @param $group_by TODO
* @param $sql_expression null|string
* @param $sql_expression_params array
* @param $cache_key CacheKey|null
* @return SqlResultProvider
*/
public function find($select, $distinct, $where, $order, $limit, $heaving = null, $group_by = null, $sql_expression = null, $sql_expression_params = array(), $cache_key = null)
{
$select = $this->db->selectExpr($select, $distinct);
$where = $this->db->whereExpr($where);
$group_by = $this->db->groupByExpr($group_by);
$order = isset($order['sort']) ? $this->order($order, $order['sort']) : false;
$limit = $this->db->limitExpr($limit);
$result = $this->query(
(($sql_expression) ? $sql_expression : ('SELECT ' . $select . ' FROM ' . $this->identify($this->table())))
. (($where) ? (' WHERE ' . $where) : '')
. (($group_by) ? (' GROUP BY ' . $group_by) : '')
. (($order) ? ($order) : '')
. (($limit) ? (' LIMIT ' . $limit) : ''),
$sql_expression_params,
$cache_key
);
return new SqlResultProvider($result);
}
public function count($select_parent_query = 'x.count', $where, $heaving = null, $group_by = null, $sql_expression = null, $sql_expression_params = array(), $cache_key = null)
{
$where = $this->db->whereExpr($where);
$group_by = $this->db->groupByExpr($group_by);
$result = $this->query(
'SELECT (' .
(($sql_expression) ? $sql_expression : ('SELECT * FROM ' . $this->identify($this->table())))
. (($where) ? (' WHERE ' . $where) : '')
. (($group_by) ? (' GROUP BY ' . $group_by) : '') . ' LIMIT 1) AS count',
$sql_expression_params,
$cache_key
);
return new SqlResultProvider($result);
}
/**
* @param $sql_expression null
* @param $sql_expression_params array
* @return SqlCriteria
*/
public function criteria($sql_expression = null, $sql_expression_params = array())
{
return new SqlCriteria($this, $sql_expression, $sql_expression_params);
}
}

View File

@ -0,0 +1,61 @@
<?php namespace Majestic\Model;
use Illuminate\Contracts\Support\Arrayable;
class SqlResultCollection extends \ArrayIterator implements iSqlResultItems, Arrayable
{
private $items;
public function __construct($items)
{
$this->items = $items;
foreach ($items as $item) {
parent::append($item);
}
}
/**
* @return DbStatement[]
*/
public function fetchAll()
{
return (array) $this;
}
/**
* @param $field
* @return mixed
*/
public function fetchField($field)
{
$item = $this->offsetGet(0);
return $item->{$field};
}
/**
* @return mixed
*/
public function fetch()
{
return $this->offsetGet(0);
}
public function assoc($field, $assoc_as_array = false) {
$sql_result_provider = new SqlResultProvider($this->items);
return $sql_result_provider->assoc($field, $assoc_as_array);
}
/**
* Get the collection of items as a plain array.
*
* @return array
*/
public function toArray()
{
return array_map(function($value)
{
return $value instanceof ArrayableInterface ? $value->toArray() : $value;
}, $this->items);
}
}

131
Model/SqlResultProvider.php Normal file
View File

@ -0,0 +1,131 @@
<?php namespace Majestic\Model;
class SqlResultProvider implements iSqlResultItems
{
/**
* @var DbStatement
*/
private $result;
/**
* @var array
* @desc my be changed in assoc method
*/
private $result_items;
/**
* @var array
*/
private $result_items_base;
/**
* @param $result DbStatement|array
*/
public function __construct($result)
{
$this->result = $result;
}
private function defineResultItems()
{
if (is_null($this->result_items_base)) {
if (is_array($this->result)) {
$this->result_items_base = $this->result;
} else {
$this->result_items_base = $this->result->fetchAll();
}
$this->result_items = $this->result_items_base;
}
}
/**
* @param $field string
* @param bool $assoc_as_array
* @return $this SqlResultProvider
* @throws \ErrorException
*/
public function assoc($field, $assoc_as_array = false)
{
$this->defineResultItems();
$result_items_assoc = array();
foreach ($this->result_items_base as $item) {
if (!property_exists($item, $field)) {
throw new \ErrorException('Undefined field. ' . $field);
}
if ($assoc_as_array) {
if (!isset($result_items_assoc[$item->{$field}])) {
$result_items_assoc[$item->{$field}] = array();
}
$result_items_assoc[$item->{$field}][] = $item;
} else {
if (isset($result_items_assoc[$item->{$field}])) {
throw new \ErrorException('Field not unique. May be use assoc_as_array. ' . $field);
}
$result_items_assoc[$item->{$field}] = $item;
}
}
// Ассоциирование внутри каждого элемента массива
if ($assoc_as_array) {
foreach ($result_items_assoc as &$value) {
$value = new SqlResultCollection($value);
}
}
$this->result_items = $result_items_assoc;
return $this;
}
public function getKeys()
{
$this->defineResultItems();
return array_keys($this->result_items);
}
/**
* @param $key
* @return mixed
* метод актуален после вызова assoc
*/
public function fetchKey($key)
{
return $this->result_items[$key];
}
/**
* @return DbStatement[]|SqlResultCollection[]
*/
public function fetchAll()
{
$this->defineResultItems();
return $this->result_items;
}
/**
* @param $field
* @return mixed
*/
public function fetchField($field)
{
if ($this->result->numRows())
{
return $this->result->fetchField($field);
} else {
return false;
}
}
/**
* @return mixed
*/
public function fetch()
{
return $this->result->fetch(Db::FETCH_OBJ);
}
/**
* @return int
*/
public function affectedRows()
{
return $this->result->affectedRows();
}
}

10
Model/iSqlResultItems.php Normal file
View File

@ -0,0 +1,10 @@
<?php namespace Majestic\Model;
interface iSqlResultItems
{
public function fetchAll();
public function fetchField($field);
public function fetch();
}

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Redis;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Redis;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -23,21 +23,21 @@ class RedisManager
* @param string $name connection name. If not set 'default' will be used. * @param string $name connection name. If not set 'default' will be used.
* @param array $config Configuration array. * @param array $config Configuration array.
* *
* @throws GeneralException * @throws \Majestic\Exception\GeneralException
* @return Redis * @return Redis
*/ */
static public function connect($name = 'default', $config = null) static public function connect($name = 'default', $config = null)
{ {
if (!isset(self::$connections[$name])) { if (!isset(self::$connections[$name])) {
if (!$config) { if (!$config) {
if (!is_object(Config::get('Redis'))) { if (!is_object(\Majestic\Config::get('Redis'))) {
throw new GeneralException('Redis config no existence'); throw new \Majestic\Exception\GeneralException('Redis config no existence');
} }
$config = Config::get('Redis')->$name; $config = \Majestic\Config::get('Redis')->$name;
} }
if (!is_array($config)) { if (!is_array($config)) {
throw new GeneralException('Connection parameters must be an array'); throw new \Majestic\Exception\GeneralException('Connection parameters must be an array');
} }
$host = isset($config['host']) ? $config['host'] : 'localhost'; $host = isset($config['host']) ? $config['host'] : 'localhost';
@ -47,16 +47,16 @@ class RedisManager
/** /**
* @var Redis * @var Redis
*/ */
$connection = new Redis(); $connection = new \Redis();
if (Config::get('PROFILER_DETAILS')) { if (\Majestic\Config::get('PROFILER_DETAILS')) {
$connection = new RedisDebug($connection); $connection = new RedisDebug($connection);
} }
if (!$connection->connect($host, $port)) { if (!$connection->connect($host, $port)) {
throw new GeneralException('Failed to connect to Redis server at ' . $host . ':' . $port); throw new \Majestic\Exception\GeneralException('Failed to connect to Redis server at ' . $host . ':' . $port);
} }
if ($database) { if ($database) {
if (!$connection->select($database)) { if (!$connection->select($database)) {
throw new GeneralException('Failed to select Redis database with index ' . $database); throw new \Majestic\Exception\GeneralException('Failed to select Redis database with index ' . $database);
} }
} }
self::$connections[$name] = $connection; self::$connections[$name] = $connection;

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Redis;
/** /**
* *
* *
@ -49,6 +49,21 @@
* @method float zScore() zScore(string $key, string $value) Returns the score of a given member in the specified sorted set. * @method float zScore() zScore(string $key, string $value) Returns the score of a given member in the specified sorted set.
* @method float zUnionStore() zUnionStore(string $destination, array $keys, array $weights = array(), string $aggregate = 'sum') Creates an union of sorted sets given in second argument and store in in first argument * @method float zUnionStore() zUnionStore(string $destination, array $keys, array $weights = array(), string $aggregate = 'sum') Creates an union of sorted sets given in second argument and store in in first argument
* @method float zInterStore() zInterStore(string $destination, array $keys, array $weights = array(), string $aggregate = 'sum') Creates an intersection of sorted sets given in second argument and store in in first argument * @method float zInterStore() zInterStore(string $destination, array $keys, array $weights = array(), string $aggregate = 'sum') Creates an intersection of sorted sets given in second argument and store in in first argument
* @method int sAdd() sAdd(string $key, string $value) Adds a value to the set value stored at key. If this value is already in the set, FALSE is returned.
* @method int sCard() sCard(string $key) Returns the cardinality of the set identified by key.
* @method int sSize() sSize(string $key) Returns the cardinality of the set identified by key.
* @method array sMembers() sMembers(string $key) Returns the contents of a set.
* @method array sGetMembers() sGetMembers(string $key) Returns the contents of a set.
* @method bool sContains() sContains(string $key, string $value) Checks if value is a member of the set stored at the key key.
* @method bool sIsMember() sIsMember(string $key, string $value) Checks if value is a member of the set stored at the key key.
* @method bool sRem() sRem(string $key, string $member) Removes the specified member from the set value stored at key.
* @method bool sRemove() sRemove(string $key, string $member) Removes the specified member from the set value stored at key.
* @method array lRange() lRange(string $key, int $start, int $end) Returns the specified elements of the list stored at the specified key in the range [start, end]. start and stop are interpretated as indices: 0 the first element, 1 the second ... -1 the last element, -2 the penultimate
* @method int rPush() rPush(string $key, string $value) Adds the string value to the tail (right) of the list. Creates the list if the key didn't exist. If the key exists and is not a list, FALSE is returned.
* @method array lTrim() lTrim(string $key, int $start, int $stop) Trims an existing list so that it will contain only a specified range of elements.
* @method array sInter
* @method bool hSet() hSet(string $key, string $hashKey, string $value) Adds a value to the hash stored at key. If this value is already in the hash, FALSE is returned.
* @method bool hGet() hGet(string $key, string $hashKey) Gets a value from the hash stored at key. If the hash table doesn't exist, or the key doesn't exist, FALSE is returned.
*/ */
class Redis class Redis
{ {

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -7,7 +7,7 @@
* @since 2010-02-17 * @since 2010-02-17
*/ */
class Registry extends ArrayObject class Registry extends \ArrayObject
{ {
/** /**
* Class name of the singleton registry object. * Class name of the singleton registry object.
@ -42,7 +42,7 @@ class Registry extends ArrayObject
} }
/** /**
* @codeCoverageIgnoreStart * @codeCoverageIgnoreEnd
*/ */
/** /**
@ -53,7 +53,7 @@ class Registry extends ArrayObject
public static function getInstance() public static function getInstance()
{ {
if (self::$_registry === null) { if (self::$_registry === null) {
self::$_registry = new self::$_class_name(); self::$_registry = new \Majestic\Registry();
} }
return self::$_registry; return self::$_registry;
} }

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru

View File

@ -1,4 +1,4 @@
<?php <?php namespace Majestic\Session;
/** /**
* @copyright NetMonsters <team@netmonsters.ru> * @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru * @link http://netmonsters.ru
@ -178,7 +178,7 @@ class Session
return; return;
} }
self::$started = true; self::$started = true;
session_start(); @session_start();
} }
/** /**

View File

@ -36,7 +36,6 @@ class LoadTest extends PHPUnit_Framework_TestCase
/** /**
* @TODO: Load->buildAutoload() should recieve AutoloadBuilder as a parameter * @TODO: Load->buildAutoload() should recieve AutoloadBuilder as a parameter
* @TODO: Load->buildAutoload() - uses two paths - PATH . '/' . APP . '/src' and PATH . '/lib' those are not checked. Can cause error.
*/ */
public function setUp() public function setUp()
{ {
@ -113,7 +112,6 @@ class LoadTest extends PHPUnit_Framework_TestCase
/** /**
* @runInSeparateProcess * @runInSeparateProcess
* @TODO: Load - check if input file returns array
*/ */
public function testFileForArray() public function testFileForArray()
{ {
@ -142,7 +140,6 @@ class LoadTest extends PHPUnit_Framework_TestCase
} }
/** /**
* @TODO: Load::getFilePath - check for wrong index
* @runInSeparateProcess * @runInSeparateProcess
*/ */
public function testAutoloadGetFilePathNullIndex() public function testAutoloadGetFilePathNullIndex()
@ -160,6 +157,7 @@ class LoadTest extends PHPUnit_Framework_TestCase
public function testDebugAutoload() public function testDebugAutoload()
{ {
$this->setConstants(); $this->setConstants();
unlink(self::$file);
Load::setAutoloadFrom(self::$file); Load::setAutoloadFrom(self::$file);
$autoload = require(self::$file); $autoload = require(self::$file);

View File

@ -28,6 +28,7 @@ require_once dirname(__FILE__) . '/../../app/AjaxAction.php';
class FrontControllerTest extends PHPUnit_Framework_TestCase class FrontControllerTest extends PHPUnit_Framework_TestCase
{ {
protected $log_file_name = 'error_log_file';
public function run(PHPUnit_Framework_TestResult $result = NULL) public function run(PHPUnit_Framework_TestResult $result = NULL)
{ {
@ -132,8 +133,6 @@ class FrontControllerTest extends PHPUnit_Framework_TestCase
{ {
$this->setConstants(false); $this->setConstants(false);
$controller = FrontController::getInstance(); $controller = FrontController::getInstance();
$result = $controller->execute();
$controller = FrontController::getInstance();
$this->assertNull($controller->execute()); $this->assertNull($controller->execute());
} }
@ -143,11 +142,14 @@ class FrontControllerTest extends PHPUnit_Framework_TestCase
public function testExecuteNoRouteDebug() public function testExecuteNoRouteDebug()
{ {
$this->setConstants(true); $this->setConstants(true);
ini_set('error_log', $this->log_file_name);
$controller = FrontController::getInstance(); $controller = FrontController::getInstance();
$result = $controller->execute(); $result = $controller->execute();
$this->assertNotEmpty($result); $this->assertNotEmpty($result);
$this->assertContains('Route for "" not found', $result); $this->assertContains('Route for "" not found', $result);
$this->assertContains('Error404Exception', $result); $this->assertContains('Error404Exception', $result);
$error = file_get_contents($this->log_file_name);
$this->assertContains('PHP Unknown Error: Error404Exception: Route for "" not found in ', $error);
} }
/** /**
@ -157,11 +159,14 @@ class FrontControllerTest extends PHPUnit_Framework_TestCase
{ {
$_SERVER['REQUEST_URI'] = '/user/account/213'; $_SERVER['REQUEST_URI'] = '/user/account/213';
$this->setConstants(true); $this->setConstants(true);
ini_set('error_log', $this->log_file_name);
$controller = FrontController::getInstance(); $controller = FrontController::getInstance();
$router = $controller->getRouter(); $router = $controller->getRouter();
$router->add('user', 'user/account/:id', 'user'); $router->add('user', 'user/account/:id', 'user');
$result = $controller->execute(); $result = $controller->execute();
$this->assertContains('Action class "userAction" not found.', $result); $this->assertContains('Action class "userAction" not found.', $result);
$error = file_get_contents($this->log_file_name);
$this->assertContains('PHP Unknown Error: GeneralException: Action class "userAction" not found. in ', $error);
} }
/** /**
@ -172,11 +177,14 @@ class FrontControllerTest extends PHPUnit_Framework_TestCase
$this->getMock('userAction'); $this->getMock('userAction');
$_SERVER['REQUEST_URI'] = '/user/account/213'; $_SERVER['REQUEST_URI'] = '/user/account/213';
$this->setConstants(true); $this->setConstants(true);
ini_set('error_log', $this->log_file_name);
$controller = FrontController::getInstance(); $controller = FrontController::getInstance();
$router = $controller->getRouter(); $router = $controller->getRouter();
$router->add('user', 'user/account/:id', 'user'); $router->add('user', 'user/account/:id', 'user');
$result = $controller->execute(); $result = $controller->execute();
$this->assertContains('Layout class "DefaultLayout" not found.', $result); $this->assertContains('Layout class "DefaultLayout" not found.', $result);
$error = file_get_contents($this->log_file_name);
$this->assertContains('PHP Unknown Error: GeneralException: Layout class "DefaultLayout" not found. in ', $error);
} }
/** /**
@ -269,6 +277,10 @@ class FrontControllerTest extends PHPUnit_Framework_TestCase
public function tearDown() public function tearDown()
{ {
unset_new_overload(); unset_new_overload();
if (file_exists($this->log_file_name) && is_writable($this->log_file_name)) {
unlink($this->log_file_name);
}
ini_set('error_log', 'php://stderr');
} }
protected function newCallback($className) protected function newCallback($className)

View File

@ -0,0 +1,179 @@
<?php
/*
* @copyright NetMonsters <team@netmonsters.ru>
* @link http://netmonsters.ru
* @package Majestic
* @subpackage UnitTests
* @since 2011-10-11
*
* Unit tests for ErrorHandler class
*/
require_once dirname(__FILE__) . '/../../classes/Env.class.php';
require_once dirname(__FILE__) . '/../../session/Session.php';
require_once dirname(__FILE__) . '/../../exception/ErrorHandler.php';
class ErrorHandlerTest extends PHPUnit_Framework_TestCase
{
public $old_eh = array('PHPUnit_Util_ErrorHandler', 'handleError');
protected $log_file_name = 'error_log_file';
public function setUp()
{
set_error_handler(array('ErrorHandler', 'error_handler'));
ob_start();
}
public function testErrorHandlerInit()
{
$my_eh = array('ErrorHandler', 'error_handler');
ErrorHandler::init();
$eh = set_error_handler($my_eh);
$this->assertInternalType('array', $eh);
$this->assertSame($eh, $my_eh);
}
public function testHandleError()
{
$this->setExpectedException('ErrorException', 'test error');
trigger_error("test error", E_USER_ERROR);
}
public function testHandleAt()
{
$my_eh = array('ErrorHandler', 'error_handler');
ErrorHandler::init();
set_error_handler($my_eh);
$var = '';
$ok = @$var['some'];
$this->assertSame('', $var);
ob_start();
$this->setExpectedException('ErrorException');
$ex = $var['some'];
}
/**
* @TODO: ErrorHandler->wrapTrace() not used
*/
public function testShowDebug()
{
try {
throw new ErrorException("test error", E_USER_ERROR);
}
catch (ErrorException $e) {
$_SESSION['some'] = 'value';
$result = ErrorHandler::showDebug($e);
$this->assertNotEmpty($result);
$this->assertStringStartsWith('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">', $result);
$this->assertStringEndsWith('</html>', $result);
}
}
/**
* @TODO: ErrorHandler::wrapTrace not used
* @TODO: nl2br() adds html <br /> but leaves original linebreak line \n
*/
public function testWrapTrace()
{
$class = new ReflectionClass('ErrorHandler');
$method = $class->getMethod('WrapTrace');
$method->setAccessible(true);
$result = $method->invoke(null, "first line\nsecond line");
$this->assertSame("<code>first line<br />\nsecond line</code>", $result);
$result = $method->invoke(null, "first line\r\nsecond line");
$this->assertSame("<code>first line<br />\r\nsecond line</code>", $result);
$result = $method->invoke(null, "first line\r\n\r\nsecond line");
$this->assertSame("<code>first line<br />\r\n<br />\r\nsecond line</code>", $result);
}
/**
* @runInSeparateProcess
*/
public function testLogErrorDefaultException()
{
$ex = new Exception('message', 123);
ini_set('error_log', $this->log_file_name);
ErrorHandler::logError($ex);
$log = file_get_contents($this->log_file_name);
$this->assertContains('PHP Unknown Error: Exception: message in ', $log);
}
/**
* @runInSeparateProcess
*/
public function testLogErrorDefaultExceptionWithHTTP()
{
$_SERVER['REQUEST_METHOD'] = 'GET';
$_SERVER['REQUEST_URI'] = '/somelongurl';
$_SERVER['HTTP_REFERER'] = 'http://referrer/url';
$this->assertEquals('GET', ENV::Server('REQUEST_METHOD'));
$this->assertEquals('/somelongurl', ENV::Server('REQUEST_URI'));
$this->assertEquals('http://referrer/url', ENV::Server('HTTP_REFERER'));
$ex = new Exception('message', 123);
ini_set('error_log', $this->log_file_name);
ErrorHandler::logError($ex);
$log = file_get_contents($this->log_file_name);
$this->assertContains('PHP Unknown Error: Exception: message in ', $log);
$this->assertContains('URL: GET /somelongurl, referrer: http://referrer/url', $log);
}
/**
* @runInSeparateProcess
*/
public function testLogErrorCustomException()
{
$ex = new LogicException('Logic', 333);
ini_set('error_log', $this->log_file_name);
ErrorHandler::logError($ex);
$log = file_get_contents($this->log_file_name);
$this->assertContains('PHP Unknown Error: LogicException: Logic in ', $log);
}
/**
* @runInSeparateProcess
*/
public function testLogErrorErrorExceptionNotice()
{
$ex = new ErrorException('message', 321, E_NOTICE);
ini_set('error_log', $this->log_file_name);
ErrorHandler::logError($ex);
$log = file_get_contents($this->log_file_name);
$this->assertContains('PHP Notice: message in ', $log);
}
/**
* @runInSeparateProcess
*/
public function testLogErrorErrorExceptionWarning()
{
$ex = new ErrorException('message', 321, E_WARNING);
ini_set('error_log', $this->log_file_name);
ErrorHandler::logError($ex);
$log = file_get_contents($this->log_file_name);
$this->assertContains('PHP Warning: message in ', $log);
}
/**
* @runInSeparateProcess
*/
public function testLogErrorErrorExceptionFatal()
{
$ex = new ErrorException('message', 321, E_ERROR);
ini_set('error_log', $this->log_file_name);
ErrorHandler::logError($ex);
$log = file_get_contents($this->log_file_name);
$this->assertContains('PHP Fatal Error: message in ', $log);
}
public function tearDown()
{
if (file_exists($this->log_file_name) && is_writable($this->log_file_name)) {
unlink($this->log_file_name);
}
ini_set('error_log', 'php://stderr');
set_error_handler($this->old_eh);
}
}

Some files were not shown because too many files have changed in this diff Show More