Библиотека для cis, online, cms1

This commit is contained in:
Фёдор Подлеснов 2016-06-29 18:51:32 +03:00
commit 3c2e614d87
269 changed files with 39854 additions and 0 deletions

24
core/adapter.php Normal file
View file

@ -0,0 +1,24 @@
<?php
/**
* Èíòåðôåéñ ê ìàññèâó è îáüåêòó êàê ê êîëëåêöèè
*/
class Adapter
{
protected $adaptee;
public function __construct ($adaptee)
{
$this->adaptee = $adaptee;
}
public function get ($name)
{
if (is_array ($this->adaptee)) {
return $this->adaptee [$name];
} else {
return $this->adaptee->$name;
}
}
}
?>

7
core/arr.php Normal file
View file

@ -0,0 +1,7 @@
<?php
class Arr {
static function get($data, $key, $default = null) {
return isset($data[$key]) ? $data[$key] : $default;
}
}

100
core/collection.php Normal file
View file

@ -0,0 +1,100 @@
<?php
/**
* Êîëëåêöèÿ
*
* package core
*/
class Collection implements ArrayAccess
{
/**
* Holds collective request data
*
* @var array
*/
protected $data = array();
/**
* Ïðåîáðàçîâàíèå ìàññèâà â êîëëåêöèþ
*
* @param array $data
*/
public function import(array $data)
{
$this->data = array_merge($this->data, $data);
return true;
}
/**
* Ïðåîáðàçîâàíèå êîëëåêöèè â ìàññèâ
*/
public function export()
{
return $this->data;
}
/**
* Store "request data" in GPC order.
*
* @param string $key
* @param mixed $value
*
* @return void
*/
public function set($key, $value)
{
$this->data[$key] = $value;
}
/**
* Read stored "request data" by referencing a key.
*
* @param string $key
*
* @return mixed
*/
public function get($key, $default = null)
{
return isset($this->data[$key]) ? $this->data[$key] : $default;
}
public function getInt($key, $default = 0)
{
return intval($this->get($key, $default));
}
public function getString($key, $default = '')
{
return ((string) $this->get($key, $default));
}
public function getNat($key, $default = 1)
{
$result = intval($this->get($key, $default));
return (($result > 0) ? $result : $default);
}
public function clear()
{
$this->data = array();
}
public function offsetSet($key, $value)
{
$this->data[$key] = $value;
}
public function offsetExists($key)
{
return isset($this->data[$key]);
}
public function offsetUnset($key)
{
unset($this->data[$key]);
}
public function offsetGet($key)
{
return isset($this->data[$key]) ? $this->data[$key] : null;
}
}

4
core/connection/all.php Normal file
View file

@ -0,0 +1,4 @@
<?php
foreach (glob(dirname(__FILE__) . "/*.php") as $file)
require_once $file;
?>

10
core/connection/data.txt Normal file
View file

@ -0,0 +1,10 @@
HTTP/1.1 200 OK
Date: Mon, 31 Mar 2008 12:38:37 GMT
Server: Apache/2.0.61 (Win32) SVN/1.4.3 mod_python/3.3.1 Python/2.4.3 PHP/5.2.5 DAV/2
X-Powered-By: PHP/5.2.5
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 6232
Connection: close
Content-Type: text/html; charset=windows-1251

View file

@ -0,0 +1,95 @@
<?php
// HttpConncectionRequest
class HttpConnection
{
const POST = "POST";
const GET = "GET";
private $param = array(); // Ïàðàìåòðû çàïðîñà
public $data = null; // Ñîäåðæàíèå
public $url; // Àäðåññ
public $method = self::GET; // Ìåòîä
public $port = 80;
public $host = "";
public $proxy_host = false;
public $proxy_port = false;
/**
* Âîçâðàùàåò çàãîëîâîê ñîåäèíåíèÿ
*/
public function getHeader()
{
$result = $this->method . " " . $this->url . " HTTP/1.1\r\n";
$result .= "Host: ". $this->host ."\r\n";
foreach ($this->param as $key => $value) {
$result .= $key . ": " . $value . "\r\n";
}
$result .= "Connection: Close\r\n\r\n";
$result .= $this->data;
return $result;
}
/**
* Óñòàíîâêà ïàðàìåòðîâ çàïðîñà
* @parma string $name
* @parma string $value
*/
public function setParameter($name, $value)
{
$this->param[$name] = $value;
}
/**
* Ìåòîä çàïðîñà GET èëè POST
*/
public function setMethod($method)
{
$this->method = $method;
}
public function setUrl($url)
{
$this->url = $url;
$this->host = parse_url($this->url, PHP_URL_HOST);
}
public function getUrl()
{
return $this->url;
}
/**
* Ñîäåðæàíèå çàïðîñà
*/
public function setContent($data)
{
$this->setParameter ("Content-length", strlen($data));
$this->data = $data;
}
/**
* Ïîñûëàåò çàïðîñ è âîçâðàùàåò ñòðàíèöó
*/
public function getPage()
{
$host = ($this->proxy_host) ? $this->proxy_host : $this->host;
$port = ($this->proxy_port) ? $this->proxy_port : $this->port;
$socket = fsockopen($host, $port, $errno, $errstr, 30);
if (! $socket) {
return null; // Exception
} else {
$header = $this->getHeader();
fwrite($socket, $header);
$result = null;
while (! feof($socket)) {
$result .= fgets($socket, 128);
}
fclose($socket);
return $result;
}
return null;
}
}

View file

@ -0,0 +1,82 @@
<?php
/**
* Îáðàáàòûâàåò HTTP îòâåò
*/
class HttpConnectionResponse
{
private $offset;
private $param = array ();
private $code;
public function __construct($response)
{
$this->offset = 0;
$this->response = $response;
$this->parseMessage();
}
/**
* Îáðàáîòêà HTTP îòâåòà
*/
private function parseMessage()
{
$http = explode(" ", $this->getLine());
$this->version = $http[0];
$this->code = $http[1];
$line = $this->getLine();
while ($offset = strpos($line, ":")) {
$this->param[substr($line, 0, $offset)] = trim(substr($line, $offset + 1));
$line = $this->getLine();
}
if (isset($this->param['Transfer-Encoding']) && $this->param['Transfer-Encoding'] == 'chunked') {
//$this->data = substr($this->response, $this->offset);
$line = hexdec($this->getLine());
$chunk = array();
while ($line > 0) {
$chunk [] = substr($this->response, $this->offset, $line);
$this->offset += $line;
$line = hexdec($this->getLine());
}
$this->data = implode("", $chunk);
} else {
$this->data = substr($this->response, $this->offset);
}
}
/**
* Îáðàáîòêà ñòðîêè HTTP îòâåòà
*/
private function getLine()
{
$begin = $this->offset;
$offset = strpos($this->response, "\r\n", $this->offset);
$result = substr($this->response, $begin, $offset - $begin);
$this->offset = $offset + 2;
return $result;
}
/**
* Çíà÷åíèå ïàðàìåòðà HTTP îòâåòà
*/
public function getParameter($name)
{
return $this->param[$name];
}
public function getData()
{
return $this->data;
}
/**
* Ñîñòîÿíèå
*/
public function getCode()
{
return $this->code;
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,433 @@
<?php
/**
*
* @package Core
*/
require_once 'core/json.php';
require_once 'core/form/form.php';
require_once 'core/controller/controller.php';
require_once 'core/widgets/pagemenu.php';
require_once 'core/widgets/menu.php';
require_once 'core/widgets/search.php';
require_once 'core/widgets/setup.php';
require_once 'core/widgets/listtable.php';
/**
* Ïåðåèìåíîâàòü êîíòðîëëåð !! (StubController, CrudController, PageController, BaseController) ModelController
* Âîçìîæíî íóæåí åùå êëàññ ñ ìåòà äåéñòâèÿìè êàê äëÿ actionIndex <= metaActionIndex ëèáî ñ êëàññàì äëÿ ýòèõ äåéñòâèé
* Åñòü êëàññ äëÿ óïðàâëåíèÿìè äåéñòâèÿìè à åñòü ñàìè äåéñòâèÿ â âèäå êëàññîâ èëè ôóíêöèé !!
*/
class Controller_Model extends Controller_Action
{
public $schema = array();
public $schemaSearch = array();
/**
* FIXME: Ëó÷øå $this->table->setHeader
*/
public $tableSchema = null;
public $formSchema = array();
public $menu;
public $path;
public $table;
public function __construct()
{
$this->path = new PathMenu();
$this->menu = new PageMenu();
$this->table = new ListTable();
}
/**
*/
function setUp()
{
$this->table->addMenuItem($this->aUrl('delete'), 'óäàëèòü', false, 'all', 'warning');
//$this->table->addMenuItem($this->nUrl('form'), 'ðåäàêòèðîâàòü', 'edit-24.png');
}
function saveParameters($args, $list)
{
foreach ($list as $item) {
$args->session()->set(array($this, $item), $args->get($item));
}
}
protected function getJSONList(/*Mapper*/ $model, Collection $request)
{
$result = array();
$this->saveParameters($request, array('size','page','desc', 'key'));
$result['list'] = $model->findAll($request, $request->get('ref'));
$result['size'] = $model->getCount($request, $request->get('ref'));
return json::encode($result);
}
/**
* Óäàëåíèå ñòîðê èç òàáëèöû
*/
public function actionDelete(HttpRequest $request)
{
$model = $this->getModel($this->useModel);
// Ïî÷åìó table_item ???
$list = ($request->get('table_item')) ? $request->get('table_item'): $request->get('id');
$model->deleteList($list);
return $this->getJSONList($model, $request);
}
/**
* Îòâåò íà çàïðîñ ïî ïîèñêó
*/
public function actionSearch(HttpRequest $request)
{
$model = $this->getModel($this->useModel);
$model->addFilter($model->requestToSQL($request, $this->formSchema));
return $this->getJSONList($model, $request);
}
/**
* Ñïèñîê ýëåìåíòîâ
*/
public function actionList(HttpRequest $request)
{
$model = $this->getModel($this->useModel);
return $this->getJSONList($model, $request);
}
private function setFormSchema()
{
require_once 'core/mapper/uimapper.php';
$model = $this->getModel($this->useModel);
$ui = new UIMapper($model);
$this->formSchema = $ui->getFormSchema();
}
/**
* Ñîõðàíåíèå ôîðìû
*/
function beforeSave(/*Model*/ $item, Collection $request)
{
if (empty($this->formSchema)) {
$this->setFormSchema();
}
// Ñäåëàòü îòîáðàæåíèå Ôîðìû â îáüåêò è îáðàòíî <-- Óáðàòü â beforeSave
foreach ($this->formSchema as $key => $conv) {
list($value, $type) = $conv;
$item->$value = call_user_func(array('Cast', 'to_' . $type), $request->get($key)); // Çäåñòü íóæíî ïðåîáðàçîâûâàòü òèï çíà÷åíèÿ
}
}
/**
* Îáíîâëåíèå ôîðìû
*/
function formUpdate(TForm $form, Collection $request)
{
}
/**
* Çàãðóçêà ôîðìû
*/
function beforeLoad(/*Model*/ $item, TForm $form)
{
if (empty($this->formSchema)) {
$this->setFormSchema();
}
// Âñòàâêà çíà÷åíèé èç äàííûõ â ôîðìó
// Îòîáðàæåíèå îáüåêòà â ïîëÿ ôîðìû
$form->fill($item, $this->formSchema);
}
// Ïðîâåðêà ââîäà
protected function validate($validator, $request)
{
}
/**
* Äåéñòâèå äëÿ ïðîâåðêè ôîðìû
*/
public function actionValidate($request)
{
require_once "core/validator/validator.php";
$validator = new Validator();
$validator->addRuleList($this->schema);
// Äåéñòâèÿ äî ïðîâåðêè ôîðìû
$this->validate($validator, $request); // <--|
$validator->validate($request); // --|
// Ïðîâåðêà ôîðìû
if (!$validator->isValid()) {
return json::encode($validator->getErrorMsg());
}
return json::encode(true);
}
/**
* Èíèöèàëèçàöèÿ ôîðìû
*/
protected function formSetup($form, $id = null, $ref = null)
{
if (empty($this->schema)) {
$model = $this->getModel($this->useModel);
$ui = new UIMapper($model);
$schema = $ui->getEditSchema();
$form->addFieldList($schema);
} else {
$form->addFieldList($this->schema);
}
}
/**
* Äîáàâëåíèå ïîëüçîâàòåëÿ
*/
public function actionAdd(HttpRequest $request)
{
require_once "core/validator/validator.php";
// {{{ òîæå ìîæåò áûòü îäèí ref èëè íåñêîëüêî
$ref = $request->get('ref');
$this->addParameter('ref', $ref); // Äîáàâëÿåò ïàðàìåòð â url
/// }}}
if ($this->checkPageId($request, $request->get('page'))) {
// Ïðîâåðêà
$validator = new Validator();
$validator->addRuleList($this->schema);
// Äåéñòâèÿ äî ïðîâåðêè ôîðìû
$this->validate($validator, $request); // <--|
$validator->validate($request); // --|
// Ïðîâåðêà ôîðìû
if (!$validator->isValid()) {
$request->setAction('form');
$this->getActionPath($request);
$form = new TForm();
$this->formSetup($form, $request->get('id'), $request->get('ref')); // Èíèöèàëèçàöèÿ ôîðìû
$form->setValues($request); // <-- Óáðàòü â formUpdate
$this->formUpdate($form, $request);
$form->setError($validator); // Óñòàíîâêà îøèáîê äëÿ ôîðìû
$tpl = $this->formPage($form, $request);
$id = $request->get('id');
if ($id) { // Ðåäàêòèðîâàíèå
$tpl->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Ñîâéñòâî ôîðìû
}
return $tpl /*->execute()*/;
}
// Íóæåí òåñò äëÿ ôîðìû
$model = $this->getModel($this->useModel);
$className = $model->className;
$item = new $className();
// Ñîõðàíÿåì çíà÷åíèå â áàçå äàííûõ
$item->id = $request->get('id');
// Åñëè òàáëèöà ñâÿçàíà ñ äðóãîé òàáëèöåé
if ($request->get('ref') && $model->reference[1]) {
$ref_id = $model->reference[1];
$item->$ref_id = $request->get('ref');
}
// Ïîäãîòîâêà ê ñîõðàíåíèþ
$this->beforeSave($item, $request); // Ñþäàæå è èñòðèÿ ïåðåõîäîâ
// nextId ??? èëè âûõîä èëè íîâàÿ ôîðìà äëÿ ñîçäàíèÿ íîâîñòè
$model->saveDB($item, $request);
}
// Äëÿ ñòðàíèöû ñî ñïèñêîì id -> èäåíòåôèêàòîð ðîäèòåëüñêîé òàáëèöû !!??
// $request->set('id', $request->get('ref'));
if ($request->get('apply')) {
$request->setAction('form');
return $this->forward('actionForm', $request);
}
return $this->forward('actionIndex', $request);
}
/**
* Çàãîëîâîê
*/
private function setTitlePath($ref)
{
if ($ref) {
$model = $this->getModel($this->useModel);
if (is_array($model->reference) && $model->reference[0]) {
$refmodel = $this->getModel($model->reference[0]);
try {
$parent = $refmodel->findById($ref);
$this->path->addTitle($parent->getTitle()); // Çàãîëîâîê ê ïîäïèñÿì ïóòåé
} catch (Exception $e) {
// Íå íàéäåí çàãîëîâîê ïîòîìó ÷òî íåïðàâèëüíî îïðåäåëåí ðîäèòåëüñêèé ýëåìåíò
}
}
}
}
/**
* Ôîðìà äëÿ ðåäàêòèðîâàíèÿ
*/
public function actionForm(HttpRequest $request)
{
$this->getActionPath($request);
$ref = $request->get('ref');
$this->addParameter('ref', $ref); // Äîáàâëÿåò ïàðàìåòð â url
$this->setTitlePath($ref);
$model = $this->getModel($this->useModel);
$form = new TForm(); // Ïîêàçûâàåì ôîðìó
$form->header = 'Ðåäàêòèðîâàíèå çàïèñè';
$this->formSetup($form, $request->get('id'), $request->get('ref')); // Èíèöèàëèçàöèÿ ôîðìû
$list = $request->get('table_item');
$id = ($list[0]) ? $list[0] : $request->get('id');
$tpl = $this->formPage ($form, $request);
if ($id) { // Ðåäàêòèðîâàíèå
$form->action = forceUrl($this->nUrl('add', array('id' => $id, 'page' => $this->getPageId($request)))); // action Ñâîéñòâî ôîðìû
$item = $model->findById($id);
// Çàãðóçêà ôîðìû
$this->beforeLoad($item, $form);
///
}
return $tpl;
}
/**
*/
function tableSetup($table, $id = null, $ref = null)
{
// FIXME: Ïîñëå çàìåíû âåçäå $tableSchema -> table->setHeader óäàëèòü!
if ($this->tableSchema) {
$table->setHeader($this->tableSchema);
} else {
// Íàñòðîéêà òàáëèöû îòîáðàæåíèÿ ïî ñõåìå äàííûõ
require_once 'core/mapper/uimapper.php';
$model = $this->getModel($this->useModel);
$ui = new UIMapper($model);
$schema = $ui->getTableSchema();
$schema[0]['action'] = $table->getFirstItem();
$table->setHeader($schema);
}
}
/**
*/
public function actionIndex(HttpRequest $request)
{
$this->getActionPath($request, 'index');
// Òàêîå ìåòà äåéñòâèå íàâåðíîå ìîæíî âûíåñòè â îòäåëüíûé êëàññ
return $this->metaActionIndex($request, array($this, 'tableSetup'), $this->aUrl('list'));
}
/**
* Ñòðàíèöà ïî óìîë÷àíèþ
*/
public function metaActionIndex(HttpRequest $request, $setup, $list)
{
// ìîæåò áûòü îäíî ref èëè íåñêîëüêî
// {{{ èñòîðèÿ ïåðåõîäîâ
$ref = null;
if ($request->get('ref')) {
$ref = $request->get('ref');
} else if ($request->session()->get('ref')) {
$ref = $request->session()->get('ref');
}
$request->session->set('ref', $ref);
$this->addParameter('ref', $ref);
// }}}
$this->setTitlePath($ref);
$tpl = $this->getView('list');
// Ïîìîøíèêè äåéñòâèé
$this->callHelpers($request);
// Òàáëèöà
if ($request->session()->get(strtolower(get_class($this)))) {
$session = $request->session()->get(strtolower(get_class($this)));
if (isset($session['view'])) {
$this->table->setView($session['view']);
}
$this->table->setData('state', array(
'page' => $session['page'],
'size' => $session['size'],
'desc' => $session['desc']));
$this->table->setData('sorter', $session['key']);
if (isset($session['desc'])) {
$this->table->setData('desc', $session['desc']);
}
}
call_user_func($setup, $this->table, $request->get('id'), $ref);// --> Ýêâèâàëåíò formSetup
$this->table->setAction($list);
//
$tpl->menu_path = $this->path->getItems();
// Ïîèñê
$search = new SearchDialog();
$search->setTitle('Ïîèñê');
$search->setAction($this->aUrl('search'));
$search->setFriend($this->table);
$search->addFields($this->schemaSearch);
// Íàñòðîéêè
$setup = new SetupDialog();
$setup->setTitle('Íàñòðîéêè');
$setup->setAction($this->nUrl('setup'));
$setup->setFriend($this->table);
// Ìåíþ
$this->menu->addMenuItem('?menu=toggle&id=' . $search->getName(), 'ïîèñê', 'actions/system-search'); // Ñòàíäàðòíûé ðàçìåð äëÿ èêîíîê 22-24px
$this->menu->addMenuItem('?menu=toggle&id=' . $setup->getName(), 'íàñòðîéêè', 'categories/applications-system');
// Äîáàâëåíèå êîìïîíåíòîâ
$this->addChild('menu', $this->menu);
$this->addChild('search', $search);
$this->addChild('setup', $setup);
$this->addChild('table', $this->table);
//
return $tpl;
}
/**
*/
public function actionSetup($request)
{
$left = explode(",", $request->get('left'));
$right = explode(",", $request->get('right'));
$$request->session()->set(strtolower(get_class($this)),
array('view' => array('left' => $left, 'right' => $right)));
return $this->forward('actionIndex', $request);
}
/**
*/
private function formPage($form, $request)
{
$view = $this->getView('form');
$view->setView('form', $form);
$view->action = forceUrl($this->nUrl('add', array('page' => $this->getPageId($request)))); // Äåéñòâèå äëÿ ôîðìû
$view->menu_path = $this->path->getItems();
$view->back = $this->path->getPrev();
return $view;
}
// Òîæå óáðàòü â ìåòîä Controller_Model
function getActionPath(HttpRequest $request/*, $action = false*/)
{
require_once 'state.php';
$this->_getActionPath()->getPath($this, ($action) ? $action : $request->getAction());
}
}

View file

@ -0,0 +1,185 @@
<?php
require_once 'core/path.php';
class FileNotFountException extends Exception
{
}
/**
* Êëàññ êîìïîíåíòà
*/
class Component
{
static $_uid = 1;
public $uid; // UID êîìïîíåíòà ñîçäàåòñÿ ïðè ñîçäàíèè ñòðàíèöû, âñòàâêè êîìïîíåíòà, èëè ýòî ñòàòè÷åñêîå ñâîéñòâî
public $viewPath;
public $registry; // Registry->getInstance
public $template;
function __construct()
{
self::$_uid ++;
$this->uid = self::$_uid;
}
function getUID()
{
return 'component:'. $this->uid;
}
public function getView($name)
{
require_once "core/view/compositeview.php";
//
$template = ($this->template) ? $this->template : $this->_registry->readKey(array('system', 'template'));
// Çàãðóæàòü øàáëîí ïî óìîë÷àíèþ åñëè íå íàéäåí òåêóùèé
if (is_dir(Path::join($this->viewPath, 'templates', $template))) {
$template_file = Path::join($this->viewPath, 'templates', $template, $name);
} else {
$template_file = Path::join($this->viewPath, 'templates', 'modern', $name);
}
$tpl = new View_Composite($template_file);
$tpl->script = $_script = Path::join(WWW_PATH, 'js');
$tpl->media = $_media = Path::join(TEMPLATE_WEB, $template);
$tpl->component = $_template = Path::join(COMPONENTS_WEB, strtolower(get_class($this)), 'templates', 'modern');
$tpl->setAlias(array(
'${media}' => $_media,
'${script}' => $_script,
'${template}' => $_template));
$tpl->loadImports(Path::skipExtension($template_file) . ".import");
return $tpl;
}
public function setParameters($view)
{
}
/**
* @param $name Èìÿ ìîäåëè
*/
private function getModelPath($name)
{
return Path::join (CMS_PATH, "model", $name . ".php");
}
/**
* Ñîçäàåò ìîäåëü
* @param string $name
* @return model
*/
public function getModel($name)
{
require_once 'core/mapper/mapper.php';
require_once ($this->getModelPath ($name));
$modelName = $name . "Mapper";
$model = new $modelName ();
$model->db = $this->db;
return $model;
}
public function options($key, $val, $res) {
$result = array();
while($res->next()) {
$result[] = array('value' => $res->getInt($key), 'name' => $res->getString($val));
}
return $result;
}
public function optionsPair($list) {
$result = array();
foreach ($list as $key => $value) {
$result [] = array('value' => $key, 'name' => $value);
}
return $result;
}
/* Â äàëüíåéøåì íóæíî çìåíèòü íà ìåòîäû
+ Ìåòîäû ìîãóò áûòü è javascript
*/
protected $editUrl;
function setEditUrl($url)
{
$this->editUrl = $url;
}
function getEditUrl()
{
return $this->editUrl;
}
}
/**
* TALES äëÿ ïîäêëþ÷åíèÿ êîìïîíåíòîâ
* component:name?param1=value1&param2=value2
*/
class Component_Tales implements PHPTAL_Tales
{
static public function component($expression, $nothrow = false)
{
return "phptal_component('" . $expression . "')";
}
}
function loadComponent($name, $db, $registry)
{
$path = Path::join(COMPONENTS, $name, $name . ".php");
// echo COMPONENTS, '<br />';
// echo $path;
if (file_exists($path)) {
require_once ($path);
$component = new $name();
$component->db = $db;
$component->_registry = $registry;
$component->viewPath = COMPONENTS."/".$name."/";
return $component;
}
throw new FileNotFountException();
}
/**
* Ôóíêöèÿ ïîäêëþ÷åíèÿ êîìïîíåíòà
*/
global $componentList;
$componentList = array();
function phptal_component ($real_expression, $offset = 0) {
global $db, $registry, $componentList; // Íóæíî êàêòî ïåðåäàâàòü ïàðàìåòðû
$expression = htmlspecialchars_decode($real_expression);
$url = parse_url($expression);
parse_str($url['query'], $arguments);
$name = $url['path'];
$component = loadComponent($name, $db, $registry);
$req = new HttpRequest();
$params = new Collection();
$params->import(array_merge($_GET, $arguments));
$component->params = $params;
$componentList [] = array(
'uid' => $component->getUID(), 'params' => $expression, 'name' => $name, 'offset' => $offset,
'size' => strlen($real_expression),
/* Âìåñòî ññûëêè íà ðåäàêòèðîâàíèå íóæíî ïåðåäàâàòü ñïèñîê ìåòîäîâ äëÿ ðàáîòû ñ êîìïîíåíòîì
edit (ðåäàêòèðîâàíèå ñîäåðæàíèå), new (íîâîå ñîäåðæàíèå), øàáëîí êîìåííåíòà ... âìåñòå ñ èêîíêàìè ýòèõ ìåòîäîâ
! Êîìïîíåíòû ìîãóò ñîäåðæàòü äðóãèå êîìïîíåíòû
*/
'editurl' => $component->getEditUrl(),
'newurl' => ''
);
unset($req['active_page']);
$component->template = $params->get('template', false);
return $component->execute($params, $req);
}
/* Ðåãèñòðàöèÿ íîâîãî ïðåôèêñà äëÿ ïîäêëþ÷åíèÿ êîìïîíåíòà */
$registry = PHPTAL_TalesRegistry::getInstance();
$registry->registerPrefix('component', array('Component_Tales', 'component'));

View file

@ -0,0 +1,334 @@
<?php
require_once 'core/path.php';
require_once 'core/mapper/factory.php';
require_once 'core/functions.php';
function forceUrl($name)
{
if (is_callable($name)) {
return call_user_func($name);
}
return $name;
}
/**
* Êîíòðîëëåð ñòðàíèö
* @package core
*/
class Controller
{
const TEMPLATE_EXTENSION = ".html"; // Ðàñøèðåíèå äëÿ øàáëîíîâ
const ACTION_PREFIX = "action"; // Ïðåôèêñ äëÿ ôóíêöèé äåéñòâèé
public $jsPath; // Ãëîáàëüíûé ïóòü ê ñêðèïòàì
public $themePath; // Ãëîáàëüíûé ïóòü ê òåêóùåé òåìå
// Ïàðàìåòðû óñòàíàâëèâàþòñÿ ïðè ñîçäàíèè êîíòðîëëåðà
public $name; // Èìÿ ìîäóëÿ
public $viewPath = null; // Ïóòü ê øàáëîíàì êîíòðîëëåðà
public $db; // Ñîåäèíåíèå ñ áàçîé äàííûõ
// Ôèëüòðû
public $access; // Îáüåêò õðàíèò ïàðàìåòðû äîñòóïà
public $logger; // Îáüåêò äëÿ âåäåíèÿ ëîãà
private $factory; // Ññûëêà íà îáüåêò ñîçäàíèÿ ìîäåëè
private $helpers = array(); // Ïîìîøíèêè äëÿ äåéñòâèé
public $param = array(); // Ïàðàìåòðû äëÿ ññûëêè
public $_registry; // Ññûëêà íà ðååñòð
public $_shortcut;
public function __construct ()
{
//
}
public function setUp ()
{
// override this
}
public function loadConfig($name) {
$filename = Shortcut::getUrl('config', $this->name, $name);
include($filename);
return $settings;
}
public function getConnection()
{
return $this->db;
}
public function installPath($name)
{
return Path::join(CMS_PATH, "modules", $name, "install");
}
public function addSuggest($view, $name)
{
$suggest = array();
$file = Path::join($this->viewPath, 'help', $name . '.suggest');
if (file_exists($file) && include($file)) {
$view->addScriptRaw("add_suggest(".json::encode($suggest).");\n");
}
}
function findIcon($icon, $size)
{
return Path::join($this->iconPath, $size . 'x' . $size, $icon . '.png');
}
/**
* Ñîçäàåò ïðåäñòàâëåíèå
* @param string $file
* @return template
*/
public function getView($name)
{
require_once "core/view/compositeview.php";
$file = $name . self::TEMPLATE_EXTENSION;
// Ñïèñîê âîçìîæíûõ äèðåêòîðèé äëÿ ïîèñêà ôàéëà øàáëîíà
$theme = $this->_registry->readKey(array('system', 'theme'));
$icon_theme = $this->_registry->readKey(array('system', 'icon_theme'));
$list = array(
Path::join($this->viewPath, TEMPLATES) => Path::join(WWW_PATH, "modules", $this->name, TEMPLATES),
PHPTAL_TEMPLATE_REPOSITORY => "");
// Ïîèñê ôàéëà äëÿ øàáëîíà
foreach($list as $ospath => $path) {
$template = Path::join($ospath, $file);
if(file_exists($template)) { break; }
}
$tpl = new View_Composite($template);
$tpl->icons = $this->iconPath; // Ïóòü ê ôàéëàì òåêóùåé òåìû
$tpl->media = $this->themePath; // Ïóòü ê ôàéëàì òåêóùåé òåìû
$tpl->script = $this->jsPath; // Ïóòü ê ôàéëàì ñêðèïòîâ
$tpl->template = $path; // Ïóòü ê ôàéëàì òåêóùåãî øàáëîíà
$tpl->setAlias(array(
'${icons}' => $this->iconPath,
'${media}' => $this->themePath,
'${script}' => $this->jsPath,
'${template}' => $path));
$tpl->loadImports(Path::skipExtension($template) . ".import");
$this->addSuggest($tpl, $name);
return $tpl;
}
public function getModel($name)
{
if (!$this->factory) {
$this->factory = new ModelFactory($this->db, $this->_registry, $this->_shortcut);
}
return $this->factory->getModel($name);
}
/**
* Âûáîð äåéñòâèÿ
* Ò.ê äåéñòâèÿ ÿâëÿþòñÿ ìåòîäàìè êëàññà òî
* 1. Ìîæíî ïåðåîïðåäåëèòü äåéñòâèÿ
* 2. Èñïîëüçîâàòü íàñëåäîâàíèå ÷òîáû äîáàâèòü ê ñòàðîìó îáðàáîò÷èêó íîâîå ïîâåäåíèå
* @param $request Îáüåêò çàïðîñà
*/
public function execute1(HTTPRequest $request)
{
$action = self::ACTION_PREFIX . ucfirst($request->getAction());
if (method_exists($this, $action)) {
return $this->forward($action, $request);
} else {
return $this->forward("actionIndex", $request);
}
}
public function execute(HTTPRequest $request)
{
$result = $this->execute1($request);
if ($result) {
$this->view = $result;
}
return $this->render();
}
public function forward($action, HTTPRequest $args)
{
// Äåéñòâèÿ äî âûçîâà îñíîâíîãî îáðàáîò÷èêà
/*foreach($this->_aspect as $aspect) {
if (isset($aspect->before[$action])) {
call_user_func ($aspect->before[$action], $action, $args);
}
}*/
return call_user_func(array($this, $action), $args);
}
/**
* Ñòðàíèöà ïî óìîë÷àíèþ
*/
public function actionIndex(HttpRequest $request)
{
return "";
}
public function postUrl($name, $param)
{
return "?" . http_build_query(
array_merge(array('module' => strtolower(get_class($this)), "action" => $name),
$this->param, $param));
}
/**
* Ãåíåðàöèÿ ññûëêè c ó÷åòîì ïðàâ ïîëüçîâàòåëÿ íà ññûëêè
*
* @parma string $name Äåéñòâèå
* @parma string $param Äîïîëíèòåëüíûå ïàðàìåòðû
*/
public function nUrl($name, array $param = array())
{
if (!$this->access || $this->access->checkAction($name)) {
return lcurry(array($this, 'postUrl'), $name, $param);
}
return null;
}
public function fUrl($name, array $param = array())
{
return forceUrl($this->nUrl($name, $param));
}
/**
* Äîáàâëÿåò ïàðàìåòð äëÿ âñåõ ññûëîê ñîçäàâàåìûõ ôóíêöèåé nUrl, aUrl
*/
public function addParameter($name, $value)
{
if ($value) {
$this->param [$name] = $value;
}
}
/**
* Ãåíåðàöèÿ ññûëêè íà äåéñòâèå êîíòðîëëåðà
* Ajax îïðåäåëÿåòñÿ àâòîìàòè÷åñêè mode = ajax èñïîëüçóåòñÿ äëÿ ñìåíû layout
*/
public function aUrl($name, array $param = array())
{
return $this->nUrl($name, array_merge(array('mode' => 'ajax'), $param)); // FIXME
}
/**
* Äîáàâëåíèå ïîìîøíèêà êîíòðîëëåðà
*/
public function addHelper($class)
{
$this->helpers [] = $class;
}
/**
* Âûçîâ ïîìîøíèêîâ êîíòðîëëåðà
*/
public function callHelpers(HttpRequest $request)
{
$action = self::ACTION_PREFIX . $request->getAction();
foreach ($this->helpers as $helper) {
if (method_exists($helper, $action)) {
return call_user_func(array($helper, $action), $request, $this);
} else {
return $helper->actionIndex($request, $this); // Âìåñòî return response ???
}
}
}
/**
* Çàãðóçêà ôàéëà êëàññà
*/
public function loadClass($path, $setup = null)
{
if (file_exists($path)) {
require_once ($path);
$class = pathinfo($path, PATHINFO_FILENAME);
return new $class($setup);
}
return null;
}
public function loadSettings($path)
{
$result = new Settings($path);
$result->read();
return $result->export();
}
// Äëÿ Widgets
public $view = null;
public $childNodes = array();
public $childViews = array();
public function setView($name)
{
$this->view = $this->getView($name);
}
/**
* Óñòàíîâêà çàãîëîâêà äëÿ îòîáðàæåíèÿ
*/
public function setTitle($title)
{
$this->view->setTitle($title);
}
/**
* Äîáàâëåíèå widget ê îòîáðàæåíèþ
*/
public function addChild(/*Widget*/ $section, $node)
{
$this->childNodes[$section] = $node;
}
/**
* Äîáàâëåíèå äî÷åðíåãî îòîáðàæåíèÿ ê òåêóùåìó îòîáðàæåíèþ
*/
public function addView(/*CompositeView*/ $section, $node)
{
$this->childViews[$section] = $node;
}
/**
* Ãåíåðàöèÿ ñîäåðæàíèÿ
* Ïóòàíèöà c execute è render
*/
public function render()
{
foreach ($this->childNodes as $name => $node) {
$node->make($this);
$this->view->setView($name, $node->view);
}
foreach ($this->childViews as $name => $node) {
$this->view->setView($name, $node);
}
return $this->view;
}
function getPageId($request)
{
$pageId = time();
$request->session()->set('page', $pageId);
return $pageId;
}
function checkPageId($request, $page)
{
$_page = $request->session()->get('page');
$result = ($_page && $_page == $page);
$request->session()->clean('page');
return $result;
}
}
class Controller_Action extends Controller {}

View file

@ -0,0 +1,92 @@
<?php
require_once 'core/controller/controller.php';
require_once 'core/controller/installer.php';
/**
* Ïåðâè÷íûé êîíòðîëëåð êîíòðîëëåð ñòðàíèö
* @package core
*/
class Controller_Front extends Controller
{
protected $shortcut; // ßðëûê ê ìîäóëþ
protected $_param; // Ïàðàìåòð ïî êîòîðîìó âûáèðàåòñÿ ìîäóëü
protected $default; // Çíà÷åíèå ïàðàìåòðà ïî óìîë÷àíèþ
protected $installer;
public function __construct(Settings $_registry, $_shortcut)
{
require_once 'creole/Creole.php';
parent::__construct();
$registry = $_registry;
$this->_registry = $_registry;
$this->_shortcut = $_shortcut;
$this->db = Creole::getConnection($registry->readKey(array('system', 'dsn')));
$this->installer = new Installer($_registry);
}
/**
* Ñîçäàåò ýêçåìïëÿð ìîäóëÿ è âûïîëíÿåò äåéñòâèÿ äëÿ íåãî
* @param string $name Èìÿ ìîäóëÿ
* @param request $request Èìÿ ìîäóëÿ
* @return string
*/
public function loadModule($name, Collection $request)
{
$this->installer->setUp($this->db, array($this, 'installPath'));
$this->installer->doUpdates($name); // ModuleLoader (1)
$moduleFile = Shortcut::getUrl($this->shortcut, $name); // ModuleLoader (2)
$module = $this->loadClass($moduleFile);
if ($module) {
// Èíèöèàëèçàöèÿ ìîäóëÿ
// $module->viewPath = dirname($moduleFile);
$module->viewPath = Shortcut::getUrl('modulepath', $name);
$module->name = $name;
$module->param = $this->param;
//
$module->_registry = $this->_registry;
$module->_shortcut = $this->_shortcut;
$module->iconPath = $this->iconPath; // -> Registry
$module->themePath = $this->themePath; // -> Registry
$module->jsPath = $this->jsPath; // -> Registry
$module->db = $this->db;
// Íå äëÿ âñåõ ïðèëîæåíèé íóæíî âåñòè ëîã äåéñòâèé
// Âåäåíèå ëîãà
$logger = $this->loadClass(FRAMEWORK_PATH . '/core/filter/actionlogger.php', $module);
$logger->before = $this->loadSettings(Shortcut::getUrl('logger', $name));
// Óïðàâëåíèå äîñòóïîì
$module->access = $this->loadClass(FRAMEWORK_PATH . '/core/filter/actionaccess.php', $logger);
$module->access->access = $this->loadSettings(Shortcut::getUrl('access', $name));
$module->setUp();
return $module->access->execute($request);
}
return null; // throw new FileNotFoundException();
}
public function setParameter($shortcut, $param, $name)
{
$this->shortcut = $shortcut;
// Ïàðàìåòð
$this->_param = $param;
$this->default = $name;
}
private function getParameter(Collection $list)
{
return ($list->get($this->_param)) ? $list->get($this->_param): $this->default;
}
public function execute(HTTPRequest $request)
{
return $this->loadModule($this->getParameter($request), $request);
}
}

View file

@ -0,0 +1,89 @@
<?php
require_once 'core/settings.php';
class Installer
{
protected $db;
protected $installPath;
public $_registry;
public function __construct(Settings $_registry)
{
$this->_registry = $_registry;
}
public function setUp($db, $installPath)
{
$this->db = $db;
$this->installPath = $installPath;
}
function getSetupFile($name)
{
return Path::join(call_user_func($this->installPath, $name), "setup.php");
}
// Ïðîâåðêà âåðñèè îáíîâëåíèÿ
function isChanged($name) // Èíôîðìàöèÿ î ìîäóëÿõ
{
$item = $this->_registry->readKey(array($name));
if ($item) {
$setup = $this->getSetupFile($name);
if (file_exists($setup) && (filemtime($setup) > $item['time'])) {
return true;
}
return false;
}
return true;
}
function installSQL(array $sql, $version_new, $version_old, $name)
{
require_once "core/setup.php";
foreach ($sql as $version => $install) {
if (version_compare($version, $version_new, "<=") && version_compare($version, $version_old, ">")) {
// this->installPath this->db
$file = Path::join(call_user_func($this->installPath, $name), "sql", $install);
Setup::batchSQL($this->db, $file);
}
}
}
// Óñòàíàâëèâàåò îáíîâëåíèÿ åñëè åñòü
function doUpdates($name, $force = false) // Óñòàíîâêà ìîäóëÿ
{
$setup = $this->getSetupFile($name);
if (file_exists($setup) && ($this->isChanged($name) || $force)) {
$registry = $this->_registry;
$settings = new Settings($setup);
$settings->read();
$item = $registry->readKey(array($name));
$version_new = $settings->get('version');
if ($item) {
$version_old = $item['version'];
} else {
$version_old = "0.0";
$registry->writeKey(array($name), array());
}
if (version_compare($version_old, $settings->get('version'), "!=")) {
$sql = $settings->get('sql');
if (is_array($sql)) {
$this->installSQL($sql, $version_new, $version_old, $name);
}
}
// Îáíîâëåíèå âåðñèè ìåíþ
$registry->writeKey(array($name), $settings->get('settings'));
$registry->writeKey(array($name),
array('version' => $version_new,
'time' => filemtime($setup)));
$registry->write();
}
}
}

79
core/controller/state.php Normal file
View file

@ -0,0 +1,79 @@
<?php
class State
{
public $action = '';
public $states = array();
public $titles = array();
public function __construct($action)
{
$this->action = $action;
}
static function make($action)
{
return new State($action);
}
public function addTitle($name, $url = array())
{
$this->titles [] = array($name, $url);
return $this;
}
public function addState(State $state)
{
$this->states [$state->getAction()] = $state;
return $this;
}
public function getAction()
{
return $this->action;
}
function checkAction($action, &$list)
{
if ($this->action == $action) {
array_push($list, $this);
return true;
} else {
foreach ($this->states as $state) {
if ($state->checkAction($action, $list)) {
array_push($list, $this);
return true;
}
}
}
return false;
}
function makeTitle($module)
{
foreach ($this->titles as $item) {
$module->path->addMenuItem($module->nUrl($this->action, $item[1]), $item[0]);
}
}
function getPath($module, $action)
{
$list = array();
if ($this->checkAction($action, $list)) {
foreach (array_reverse($list) as $item) {
$item->makeTitle($module);
}
} else {
$this->makeTitle($module);
}
}
}
/*
$path = State::make('index')
->addState(State::make('form'))
->addState(State::make('view'));
$path->getPath(0, 'form');
*/

26
core/data/areas.php Normal file
View file

@ -0,0 +1,26 @@
<?php
$Areas = array
(
0 => '',
1 => 'Город Ярославль',
2 => 'Большесельский район',
3 => 'Борисоглебский район',
4 => 'Брейтовский район',
5 => 'Гаврилов-Ямский район',
6 => 'Даниловский район',
7 => 'Любимский район',
8 => 'Мышкинский район',
9 => 'Некоузский район',
10 => 'Некрасовский район',
11 => 'Переславский район',
12 => 'Первомайский район',
13 => 'Пошехонский район',
14 => 'Ростовский район',
15 => 'Рыбинский район',
16 => 'Тутаевский район',
17 => 'Угличский район',
18 => 'Ярославский район',
19 => 'Город Переславль',
20 => 'Город Рыбинск'
);

28
core/data/city.php Normal file
View file

@ -0,0 +1,28 @@
<?php
global $TypeCity, $TypeCityShort;
// Массив типов поселений
$TypeCity = array(
// 0 => '',
1 => 'город',
2 => 'село',
3 => 'поселок',
4 => 'деревня',
5 => 'поселок городского типа',
6 => 'рабочий поселок',
7 => 'станица',
8 => 'аул'
);
$TypeCityShort = array(
0 => '',
1 => 'г.',
2 => 'с.',
3 => 'п.',
4 => 'д.',
5 => 'пгт.',
6 => 'р.п.',
7 => 'ст.',
8 => 'а.'
);

196
core/data/mime.php Normal file
View file

@ -0,0 +1,196 @@
<?php
/**
* http://www.w3schools.com/media/media_mimeref.asp
*/
$_mime_type = array (
"" => "application/octet-stream",
"323" => "text/h323",
"acx" => "application/internet-property-stream",
"ai" => "application/postscript",
"aif" => "audio/x-aiff",
"aifc" => "audio/x-aiff",
"aiff" => "audio/x-aiff",
"asf" => "video/x-ms-asf",
"asr" => "video/x-ms-asf",
"asx" => "video/x-ms-asf",
"au" => "audio/basic",
"avi" => "video/x-msvideo",
"axs" => "application/olescript",
"bas" => "text/plain",
"bcpio" => "application/x-bcpio",
"bin" => "application/octet-stream",
"bmp" => "image/bmp",
"c" => "text/plain",
"cat" => "application/vnd.ms-pkiseccat",
"cdf" => "application/x-cdf",
"cer" => "application/x-x509-ca-cert",
"class" => "application/octet-stream",
"clp" => "application/x-msclip",
"cmx" => "image/x-cmx",
"cod" => "image/cis-cod",
"cpio" => "application/x-cpio",
"crd" => "application/x-mscardfile",
"crl" => "application/pkix-crl",
"crt" => "application/x-x509-ca-cert",
"csh" => "application/x-csh",
"css" => "text/css",
"dcr" => "application/x-director",
"der" => "application/x-x509-ca-cert",
"dir" => "application/x-director",
"dll" => "application/x-msdownload",
"dms" => "application/octet-stream",
"doc" => "application/msword",
"dot" => "application/msword",
"dvi" => "application/x-dvi",
"dxr" => "application/x-director",
"eps" => "application/postscript",
"etx" => "text/x-setext",
"evy" => "application/envoy",
"exe" => "application/octet-stream",
"fif" => "application/fractals",
"flr" => "x-world/x-vrml",
"gif" => "image/gif",
"gtar" => "application/x-gtar",
"gz" => "application/x-gzip",
"h" => "text/plain",
"hdf" => "application/x-hdf",
"hlp" => "application/winhlp",
"hqx" => "application/mac-binhex40",
"hta" => "application/hta",
"htc" => "text/x-component",
"htm" => "text/html",
"html" => "text/html",
"htt" => "text/webviewhtml",
"ico" => "image/x-icon",
"ief" => "image/ief",
"iii" => "application/x-iphone",
"ins" => "application/x-internet-signup",
"isp" => "application/x-internet-signup",
"jfif" => "image/pipeg",
"jpe" => "image/jpeg",
"jpeg" => "image/jpeg",
"jpg" => "image/jpeg",
"js" => "application/x-javascript",
"latex" => "application/x-latex",
"lha" => "application/octet-stream",
"lsf" => "video/x-la-asf",
"lsx" => "video/x-la-asf",
"lzh" => "application/octet-stream",
"m13" => "application/x-msmediaview",
"m14" => "application/x-msmediaview",
"m3u" => "audio/x-mpegurl",
"man" => "application/x-troff-man",
"mdb" => "application/x-msaccess",
"me" => "application/x-troff-me",
"mht" => "message/rfc822",
"mhtml" => "message/rfc822",
"mid" => "audio/mid",
"mny" => "application/x-msmoney",
"mov" => "video/quicktime",
"movie" => "video/x-sgi-movie",
"mp2" => "video/mpeg",
"mp3" => "audio/mpeg",
"mpa" => "video/mpeg",
"mpe" => "video/mpeg",
"mpeg" => "video/mpeg",
"mpg" => "video/mpeg",
"mpp" => "application/vnd.ms-project",
"mpv2" => "video/mpeg",
"ms" => "application/x-troff-ms",
"mvb" => "application/x-msmediaview",
"nws" => "message/rfc822",
"oda" => "application/oda",
"p10" => "application/pkcs10",
"p12" => "application/x-pkcs12",
"p7b" => "application/x-pkcs7-certificates",
"p7c" => "application/x-pkcs7-mime",
"p7m" => "application/x-pkcs7-mime",
"p7r" => "application/x-pkcs7-certreqresp",
"p7s" => "application/x-pkcs7-signature",
"pbm" => "image/x-portable-bitmap",
"pdf" => "application/pdf",
"pfx" => "application/x-pkcs12",
"pgm" => "image/x-portable-graymap",
"pko" => "application/ynd.ms-pkipko",
"pma" => "application/x-perfmon",
"pmc" => "application/x-perfmon",
"pml" => "application/x-perfmon",
"pmr" => "application/x-perfmon",
"pmw" => "application/x-perfmon",
"pnm" => "image/x-portable-anymap",
"pot," => "application/vnd.ms-powerpoint",
"ppm" => "image/x-portable-pixmap",
"pps" => "application/vnd.ms-powerpoint",
"ppt" => "application/vnd.ms-powerpoint",
"prf" => "application/pics-rules",
"ps" => "application/postscript",
"pub" => "application/x-mspublisher",
"qt" => "video/quicktime",
"ra" => "audio/x-pn-realaudio",
"ram" => "audio/x-pn-realaudio",
"ras" => "image/x-cmu-raster",
"rgb" => "image/x-rgb",
"rmi" => "audio/mid",
"roff" => "application/x-troff",
"rtf" => "application/rtf",
"rtx" => "text/richtext",
"scd" => "application/x-msschedule",
"sct" => "text/scriptlet",
"setpay" => "application/set-payment-initiation",
"setreg" => "application/set-registration-initiation",
"sh" => "application/x-sh",
"shar" => "application/x-shar",
"sit" => "application/x-stuffit",
"snd" => "audio/basic",
"spc" => "application/x-pkcs7-certificates",
"spl" => "application/futuresplash",
"src" => "application/x-wais-source",
"sst" => "application/vnd.ms-pkicertstore",
"stl" => "application/vnd.ms-pkistl",
"stm" => "text/html",
"svg" => "image/svg+xml",
"sv4cpio" => "application/x-sv4cpio",
"sv4crc" => "application/x-sv4crc",
"swf" => "application/x-shockwave-flash",
"t" => "application/x-troff",
"tar" => "application/x-tar",
"tcl" => "application/x-tcl",
"tex" => "application/x-tex",
"texi" => "application/x-texinfo",
"texinfo" => "application/x-texinfo",
"tgz" => "application/x-compressed",
"tif" => "image/tiff",
"tiff" => "image/tiff",
"tr" => "application/x-troff",
"trm" => "application/x-msterminal",
"tsv" => "text/tab-separated-values",
"txt" => "text/plain",
"uls" => "text/iuls",
"ustar" => "application/x-ustar",
"vcf" => "text/x-vcard",
"vrml" => "x-world/x-vrml",
"wav" => "audio/x-wav",
"wcm" => "application/vnd.ms-works",
"wdb" => "application/vnd.ms-works",
"wks" => "application/vnd.ms-works",
"wmf" => "application/x-msmetafile",
"wps" => "application/vnd.ms-works",
"wri" => "application/x-mswrite",
"wrl" => "x-world/x-vrml",
"wrz" => "x-world/x-vrml",
"xaf" => "x-world/x-vrml",
"xbm" => "image/x-xbitmap",
"xla" => "application/vnd.ms-excel",
"xlc" => "application/vnd.ms-excel",
"xlm" => "application/vnd.ms-excel",
"xls" => "application/vnd.ms-excel",
"xlt" => "application/vnd.ms-excel",
"xlw" => "application/vnd.ms-excel",
"xof" => "x-world/x-vrml",
"xpm" => "image/x-xpixmap",
"xwd" => "image/x-xwindowdump",
"z" => "application/x-compress",
"zip" => "application/zip",
);

35
core/data/okato.php Normal file
View file

@ -0,0 +1,35 @@
<?php
// В ОКАТО приняты следующие сокращения:
// http://www.consultant.ru/online/base/?req=doc;base=LAW;n=62484
$_okato = array (
"р" => "район",
"г" => "город",
"пгт" => "поселок городского типа",
"рп" => "рабочий поселок",
"кп" => "курортный поселок",
"к" => "кишлак",
"пс" => "поселковый совет",
"сс" => "сельсовет",
"смн" => "сомон",
"вл" => "волость",
"дп" => "дачный поселковый совет",
"п" => "поселок сельского типа",
"нп" => "населенный пункт",
"п. ст" => "поселок при станции",
"ж/д ст" => "железнодорожная станция",
"с" => "село",
"м" => "местечко",
"д" => "деревня",
"сл" => "слобода",
"ст" => "станция",
"ст-ца" => "станица",
"х" => "хутор",
"у" => "улус",
"рзд" => "разъезд",
"клх" => "колхоз",
"им" => "имени",
"свх" => "совхоз",
"зим" => "зимовье",
);

92
core/data/regions.php Normal file
View file

@ -0,0 +1,92 @@
<?php
global $Regions;
$Regions = array (
0 => '',
2 => 'Алтайский край',
3 => 'Амурская область',
4 => 'Архангельская область',
5 => 'Астраханская область',
6 => 'Белгородская область',
7 => 'Брянская область',
8 => 'Владимирская область',
9 => 'Волгоградская область',
10 => 'Вологодская область',
11 => 'Воронежская область',
12 => 'г. Москва',
13 => 'г. Санкт-Петербург',
14 => 'Еврейская автономная область',
84 => 'Забайкальский край',
15 => 'Ивановская область',
16 => 'Иркутская область',
17 => 'Кабардино-Балкарская Республика',
18 => 'Калининградская область',
19 => 'Калужская область',
20 => 'Камчатский край',
21 => 'Карачаево-Черкесская Республика',
22 => 'Кемеровская область',
23 => 'Кировская область',
28 => 'Костромская область',
29 => 'Краснодарский край',
30 => 'Красноярский край',
31 => 'Курганская область',
32 => 'Курская область',
33 => 'Ленинградская область',
34 => 'Липецкая область',
35 => 'Магаданская область',
36 => 'Московская область',
37 => 'Мурманская область',
38 => 'Ненецкий автономный округ',
39 => 'Нижегородская область',
40 => 'Новгородская область',
41 => 'Новосибирская область',
42 => 'Омская область',
43 => 'Оренбургская область',
44 => 'Орловская область',
45 => 'Пензенская область',
46 => 'Пермский край',
47 => 'Приморский край',
48 => 'Псковская область',
49 => 'Республика Адыгея',
50 => 'Республика Алтай',
51 => 'Республика Башкортостан',
52 => 'Республика Бурятия',
25 => 'Республика Дагестан',
26 => 'Республика Ингушетия',
53 => 'Республика Калмыкия',
54 => 'Республика Карелия',
55 => 'Республика Коми',
56 => 'Республика Марий Эл',
57 => 'Республика Мордовия',
58 => 'Республика Саха(Якутия)',
59 => 'Республика Северная Осетия-Алания',
60 => 'Республика Татарстан',
61 => 'Республика Тыва',
62 => 'Республика Хакасия',
63 => 'Ростовская область',
64 => 'Рязанская область',
65 => 'Самарская область',
66 => 'Саратовская область',
67 => 'Сахалинская область',
68 => 'Свердловская область',
69 => 'Смоленская область',
70 => 'Ставропольский край',
71 => 'Таймырский (Долгано-Ненецкий) автономный округ',
72 => 'Тамбовская область',
73 => 'Тверская область',
74 => 'Томская область',
75 => 'Тульская область',
76 => 'Тюменская область',
77 => 'Удмуртская Республика',
78 => 'Ульяновская область',
80 => 'Хабаровский край',
81 => 'Ханты-Мансийский автономный округ',
82 => 'Челябинская область',
83 => 'Чеченская Республика',
85 => 'Чувашская Республика',
86 => 'Чукотский автономный округ',
87 => 'Эвенкийский автономный округ',
88 => 'Ямало-Ненецкий автономный округ',
89 => 'Ярославская область'
);

35
core/data/states.php Normal file
View file

@ -0,0 +1,35 @@
<?php
$_states = array (
0 => array('title' => ''),
1 => array(
'title' => 'Центральный федеральный округ',
'short' => 'ЦФО',
'regions' => array(6, 7, 8, 11, 12, 15, 19, 28, 32, 34, 36, 44, 64, 69, 72, 73, 75, 89)),
2 => array(
'title' => 'Южный федеральный округ',
'short' => 'ЮФО',
'regions' => array(5, 9, 17, 21, 29, 49, 25, 26, 53, 59, 63, 70, 83)),
3 => array(
'title' => 'Северо-западный федеральный округ',
'short' => 'СЗФО',
'regions' => array(4, 10, 13, 18, 33, 37, 38, 40, 48, 54, 55)),
4 => array(
'title' => 'Дальневосточный федеральный округ',
'short' => 'ДФО',
'regions' => array(3, 14, 20, 35, 47, 58, 67, 80, 86)),
5 => array(
'title' => 'Сибирский федеральный округ',
'short' => 'СФО',
'regions' => array(2, 16, 22, 30, 41, 42, 50, 52, 61, 62, 71, 74, 84, 86, 87)),
6 => array(
'title' => 'Уральский федеральный округ',
'short' => 'УФО',
'regions' => array(31, 68, 76, 81, 82, 88)),
7 => array(
'title' => 'Приволжский федеральный округ',
'short' => 'ПФО',
'regions' => array(23, 39, 43, 45, 46, 51, 56, 57, 60, 65, 66, 77, 78, 85)));
$States = &$_states;

18
core/database.php Normal file
View file

@ -0,0 +1,18 @@
<?php
/**
* Ïðîñòîé êëàññ(Factory) äëÿ ðàáîòû ñ áàçàìè äàííûõ
*/
class Database
{
static function getConnection (array $dsn)
{
require_once "core/drivers/database." . strtolower($dsn['phptype']) . ".php";
$name = "Database_" . strtoupper($dsn['phptype']);
$database = new $name();
$database->connect($dsn);
return $database;
}
}
?>

305
core/database_pdo.php Normal file
View file

@ -0,0 +1,305 @@
<?php
/**
* Êëàññ îáîëî÷êà äëÿ PDO äëÿ çàìåíû Creole
*/
class Database extends PDO
{
public function __construct($dsn, $username = false, $password = false)
{
parent::__construct($dsn, $username, $password);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDODatabaseStatement', array()));
}
public function getDSN()
{
return $this->dsn;
}
static function getConnection(array $dsn)
{
if ($dsn['phptype'] == 'pgsql') {
$port = (isset($dsn['port'])) ? "port={$dsn['port']};" : "";
$connection = new Database("{$dsn['phptype']}:host={$dsn['hostspec']}; $port dbname={$dsn['database']}", $dsn['username'], $dsn['password']);
}
if ($dsn['phptype'] == 'sqlite') {
$connection = new Database("{$dsn['phptype']}:{$dsn['database']}");
}
$connection->dsn = $dsn;
return $connection;
}
public function executeQuery($query)
{
$sth = $this->prepare($query);
$sth->setFetchMode(PDO::FETCH_ASSOC);
$sth->execute();
// print_r($sth->fetchAll());
return $sth;//$sth->fetchAll();
}
public function prepareStatement($query)
{
return new DatabaseStatement($query, $this);
}
// Äëÿ ñîâìåñòèìîñòè ñî ñòàðûì ïðåäñòàâëåíèåì áàç äàííûõ CIS
public function fetchAllArray($query)
{
$sth = $this->prepare($query);
$sth->setFetchMode(PDO::FETCH_ASSOC);
$sth->execute();
return $sth->fetchAll();
}
public function fetchOneArray($query)
{
$sth = $this->prepare($query);
$sth->setFetchMode(PDO::FETCH_ASSOC);
$sth->execute();
return $sth->fetch();
}
private function assignQuote($x, $y)
{
return $x . "=" . $this->quote($y);
}
function insertQuery($table, array $values)
{
return $this->query("INSERT INTO $table (" . implode(",", array_keys($values))
. ") VALUES (" . implode(",", array_map(array($this, 'quote'), array_values($values))) . ")");
}
function updateQuery($table, array $values, $cond)
{
return $this->query("UPDATE $table SET " . implode(",",
array_map(array($this, 'assignQuote'), array_keys($values), array_values($values))) . " WHERE $cond");
}
function getNextId($seq)
{
$result = $this->fetchOneArray("SELECT nextval('$seq')");
return $result['nextval'];
}
function close()
{
return null;
}
}
class PDODatabaseStatementIterator implements Iterator
{
private $result;
private $pos = 0;
private $fetchmode;
private $row_count;
private $rs;
/**
* Construct the iterator.
* @param PgSQLResultSet $rs
*/
public function __construct($rs)
{
$this->result = $rs;
$this->row_count = $rs->getRecordCount();
}
function rewind()
{
// echo 'rewind';
$this->pos = 0;
}
function valid()
{
return ( $this->pos < $this->row_count );
}
function key()
{
return $this->pos;
}
function current()
{
return $this->result->fetch(PDO::FETCH_ASSOC);
}
function next()
{
$this->pos++;
}
function seek ( $index )
{
$this->pos = $index;
}
function count ( ) {
return $this->row_count;
}
}
class PDODatabaseStatement extends PDOStatement implements IteratorAggregate
{
protected $cursorPos = 0;
function getIterator()
{
// echo 'getiterator';
return new PDODatabaseStatementIterator($this);
}
protected function __construct() {
}
function rewind()
{
// echo 'rewind';
$this->cursorPos = 0;
}
public function seek($rownum)
{
// echo 'seek';
if ($rownum < 0) {
return false;
}
// PostgreSQL rows start w/ 0, but this works, because we are
// looking to move the position _before_ the next desired position
$this->cursorPos = $rownum;
return true;
}
function valid()
{
// echo 'valid';
return ( true );
}
public function first()
{
// echo 'first';
if($this->cursorPos !== 0) { $this->seek(0); }
return $this->next();
}
function next()
{
// echo 'next';
if ($this->getRecordCount() > $this->cursorPos) {
$this->fields = $this->fetch(PDO::FETCH_ASSOC);
} else {
$this->fields = null;
}
// $this->cursorPos++;
return true;
}
function key() {
// echo 'key';
return $this->cursorPos;
}
function current()
{
// echo 'current';
return $this->result->fetch(PDO::FETCH_ASSOC);
}
function getRow()
{
return $this->fields;
}
function getInt($name)
{
return intval($this->fields[$name]);
}
function getBlob($name)
{
return $this->fields[$name];
}
function getString($name)
{
return $this->fields[$name];
}
function get($name)
{
return $this->cursorPos[$name];
}
function getRecordCount()
{
return $this->rowCount();
}
}
/**
* Êëàññ îáîëî÷êà äëÿ PDOStatement äëÿ çàìåíû Creole
*/
class DatabaseStatement
{
protected $limit = null;
protected $offset = null;
protected $statement = null;
protected $binds = array();
protected $conn;
protected $query;
function __construct($query, $conn) {
$this->query = $query;
$this->conn = $conn;
}
function setInt($n, $value)
{
$this->binds [] = array($n, $value, PDO::PARAM_INT);
}
function setString($n, $value)
{
$this->binds [] = array($n, $value, PDO::PARAM_STR);
}
function setBlob($n, $value)
{
$this->binds [] = array($n, $value, PDO::PARAM_BLOB);
}
function setLimit($limit)
{
$this->limit = $limit;
}
function setOffset($offset)
{
$this->offset = $offset;
}
function executeQuery()
{
if ($this->limit) {
$this->queryString .= " LIMIT {$this->limit} OFFSET {$this->offset}";
}
$stmt = $this->conn->prepare($this->query);
foreach ($this->binds as $bind) {
list($n, $value, $type) = $bind;
$stmt->bindValue($n, $value, $type);
}
$stmt->setFetchMode(PDO::FETCH_ASSOC);
$stmt->execute();
return $stmt;
}
}

View file

@ -0,0 +1,50 @@
<?php
require_once 'core/drivers/db.php';
/**
* Ïðîñòîé êëàññ äëÿ ðàáîòû ñ áàçàìè äàííûõ
*/
class Database_MYSQL extends DB implements IDatabase
{
public function connect(array $dsn)
{
$db = @mysql_pconnect($dsn['hostspec'], $dsn['username'], $dsn['password'])
or die("Unable connect to database!");
mysql_select_db($dsn['database']);
return ($this->db = $db);
}
public function close()
{
return mysql_close($this->db);
}
public function query($query)
{
$res = mysql_query($this->db, $query)
or die("Error: wrong SQL query #$query#");
return $res;
}
public function fetchAllArray($query)
{
$res = $this->query($query);
while ($row = mysql_fetch_array ($res))
$rows[] = $row;
mysql_free_result($res);
return ($rows) ? $rows : array();
}
public function fetchOneArray($query)
{
$res = $this->query($query);
$row = mysql_fetch_array($res);
mysql_free_result($res);
return ($row) ? $row : array();
}
}
?>

View file

@ -0,0 +1,54 @@
<?php
require_once 'core/drivers/db.php';
/**
* Ïðîñòîé êëàññ äëÿ ðàáîòû ñ áàçàìè äàííûõ
*/
class Database_ODBC extends DB implements IDatabase
{
public function connect(array $dsn)
{
$db = @odbc_connect($dsn['database'], $dsn['username'], $dsn['password'])
or die("Unable connect to database!");
return ($this->db = $db);
}
public function close()
{
return odbc_close($this->db);
}
public function query($query)
{
$res = odbc_exec($this->db, $query)
or die("Error: wrong SQL query #$query#");
return $res;
}
public function fetchAllArray($query)
{
$res = $this->query($query);
$to = odbc_num_fields($res);
while (odbc_fetch_row($res)) {
for ($i = 1; $i <= $to; $i++) {
$row [odbc_field_name($res, $i)] = trim(odbc_result($res, $i));
}
$rows[] = $row;
}
return ($rows)? $rows : array();
}
public function fetchOneArray($query)
{
$res = $this->query($query);
if (!odbc_fetch_row($res)) return array ();
$to = odbc_num_fields($res);
for ($i = 1; $i <= $to; $i++) {
$row [odbc_field_name($res, $i)] = trim(odbc_result($res, $i));
}
return $row;
}
}
?>

View file

@ -0,0 +1,74 @@
<?php
require_once 'core/drivers/db.php';
/**
* Ïðîñòîé êëàññ äëÿ ðàáîòû ñ áàçàìè äàííûõ
*/
class Database_PGSQL extends DB implements IDatabase
{
public function connect(array $dsn)
{
if (isset($dsn['port'])) {
$port = "port={$dsn['port']}";
} else {
$port = "port=5432";
}
$str = "host={$dsn['hostspec']} $port dbname={$dsn['database']} user={$dsn['username']} password={$dsn['password']}";
$db = @pg_connect($str)
or die("Unable connect to database!");
return ($this->db = $db);
}
public function close()
{
return pg_close($this->db);
}
public function query($query)
{
$res = pg_query($this->db, $query)
or die("Error: wrong SQL query #$query#");
return $res;
}
public function fetchAllArray($query, $type = PGSQL_ASSOC)
{
$res = $this->query($query);
$rows = array();
while ($row = pg_fetch_array($res, NULL, $type)) {
$rows[] = $this->clean($row);
}
pg_free_result($res);
return ($rows) ? $rows : array();
}
public function affectedRows()
{
return pg_affected_rows($this->db);
}
private function clean($row)
{
foreach ($row as $key => $value) {
$row[$key] = trim($value);
}
return $row;
}
public function fetchOneArray($query, $type = PGSQL_ASSOC)
{
$res = $this->query($query);
$row = pg_fetch_array($res, NULL, $type);
pg_free_result($res);
return ($row) ? $this->clean($row) : array();
}
function getNextId($seq)
{
$result = $this->fetchOneArray("SELECT nextval('$seq')");
return $result['nextval'];
}
}

50
core/drivers/db.php Normal file
View file

@ -0,0 +1,50 @@
<?php
/**
* Èíòåðôåéñ äðàéâåðà êëàññà áàç äàííûõ
*/
interface IDatabase
{
public function connect(array $dsn);
public function close();
public function query($query);
public function fetchAllArray($query);
public function fetchOneArray($query);
}
abstract class DB implements IDatabase
{
const limit = 1024;
protected $db;
public static function quote($x)
{
return "'" . $x . "'";
}
private static function assign_quote($x, $y)
{
return $x . "='" . $y . "'";
}
function insert($table, array $values)
{
return $this->query("INSERT INTO $table (" . implode(",", array_keys($values))
. ") VALUES (" . implode(",", array_map(array('self', 'quote'), array_values($values))) . ")");
}
function update($table, array $values, $cond)
{
return $this->query("UPDATE $table SET " . implode(",",
array_map(array('self', 'assign_quote'), array_keys($values), array_values($values))) . " WHERE $cond");
}
function check_text($text)
{
if(strlen($text) > self::limit) $text = substr($text, 0, self::limit);
$text = htmlspecialchars(trim($text));
return $text;
}
}
?>

86
core/error.php Normal file
View file

@ -0,0 +1,86 @@
<?php
// Report simple running errors
define('ERROR_FILE', 'phedor@edu.yar.ru');
define('ERROR_TYPE', 1);
ini_set('error_reporting', 0);
ini_set('display_errors', 0);
error_reporting(0);
function get_error_name($id) {
$names = array(1 => 'E_ERROR',
2 => 'E_WARNING',
4 => 'E_PARSE',
8 => 'E_NOTICE',
16 => 'E_CORE_ERROR',
32 => 'E_CORE_WARNING',
64 => 'E_COMPILE_ERROR',
128 => 'E_COMPILE_WARNING',
256 => 'E_USER_ERROR',
512 => 'E_USER_WARNING',
1024 => 'E_USER_NOTICE',
2048 => 'E_STRICT',
4096 => 'E_RECOVERABLE_ERROR',
8192 => 'E_DEPRECATED',
16384 => 'E_USER_DEPRECATED',
30719 => 'E_ALL');
return $names[$id];
}
function send_error($description) {
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
$message .= "post:" . var_export($_POST, true) . "\n";
$message .= "description: " . $description;
// error_log($message, ERROR_TYPE, ERROR_FILE);
return false;
}
function error_handler($errno, $errstr, $errfile, $errline) {
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
$message .= "post:" . var_export($_POST, true) . "\n";
$message .= "type: " . get_error_name($errno) . "\n"
. "error: " . $errstr . "\n"
. "line: " . $errline . "\n"
. "file: " . $errfile;
// error_log($message, ERROR_TYPE, ERROR_FILE);
return false;
}
function shutdown() {
$error = error_get_last();
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
if (is_array($error)) {
foreach ($error as $info => $string) {
$message .= "{$info}: {$string}\n";
}
}
error_log($message, ERROR_TYPE, ERROR_FILE);
}
function exception_handler($exception) {
$message = "request: " . "http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'] . "\n";
$message .= "from: " . $_SERVER['REMOTE_ADDR'] . "\n";
if(isset($_SERVER['HTTP_REFERER'])) $message .= "referer: " . $_SERVER['HTTP_REFERER'] . "\n";
$message .=
"file: " . $exception->getFile() . "\n"
. "line: " . $exception->getLine() . "\n"
. "message: " . $exception->getMessage() . "\n"
. "trace: " . $exception->getTraceAsString();
error_log($message, ERROR_TYPE, ERROR_FILE);
return true;
}
set_exception_handler('exception_handler');
set_error_handler("error_handler");
//register_shutdown_function('shutdown');

82
core/file.php Normal file
View file

@ -0,0 +1,82 @@
<?php
require_once 'core/sort.php';
//Ñòàíîâèòüñÿ ïîõîæå íà ðàáîòó ôàéëîâ ÷åðåç SPL âîçìîæíî ñòîèò ðåàëèçîâàòü íà áàçå åãî
class FileRecord
{
public $file;
protected $src;
protected $parent;
function __construct(array $file, $src, $parent = false)
{
$this->file = $file;
$this->filename = $src;
$this->parent = $parent;
}
function get($name) {
return isset($this->file[$name]) ? $this->file[$name] : null;
}
function fileStat()
{
$type = is_dir($this->filename);
return array(
'name' => ($this->parent) ? ".." : $this->getName(),
'type' => $type,
'extension' => ($type) ? 'folder' : pathinfo($this->filename, PATHINFO_EXTENSION),
'date' => date("d.m.Y H:i", $this->getTime()),
'access' => 0,
'size' => ($type) ? "" : $this->getSizeString(),
'state' => isset($this->file['state']) ? $this->file['state'] : 'unknown',
'title' => $this->getTitle(),
/*'author' => $this->file['author'],
'description' => $this->file['description'],
'keywords' => $this->file['keywords'],*/
);
}
function isExpected()
{
if (isset($this->file['state'])) {
return ($this->file['state'] == 'expected');
}
return false;
}
function getSizeString()
{
$size = $this->getSize();
foreach (array('á ', 'Ká', 'Má') as $suffix) {
if (($size / 1024) <= 1) {
return round($size, 0) . ' ' . $suffix;
}
$size /= 1024;
}
return round($size, 0) . ' GB';
}
function getSize()
{
return ($this->isExpected()) ? 0 : filesize($this->filename);
}
function getTime()
{
return ($this->isExpected()) ? 0 : filemtime($this->filename);
}
function getName()
{
return pathinfo($this->filename, PATHINFO_BASENAME);
}
function getTitle()
{
return isset($this->file['title']) ? $this->file['title'] : $this->getName();
}
}
?>

583
core/filesystem.php Normal file
View file

@ -0,0 +1,583 @@
<?php
require_once 'core/path.php';
require_once 'core/file.php';
interface IFileSystem
{
// Îïåðàöèè íàä ôàéëàìè
public function makeDirectory($name);
public function deleteDirectory($name);
public function deleteFile($name);
public function renameFile($source, $destination);
public function copyFile($source, $destination);
public function moveUploadedFile($source, $destination);
// deleteDirectoryRecursive
public function isDir($name);
public function readFile($source);
public function writeFile($source, $content);
// Ñîäåðæàíèå äèðåêòîðèè
public function directoryFiles($name);
public function directoryFilesRecursive($name);
}
interface IFileControl
{
public function commitFile($name, $who, $message);
public function readFileVersion($name, $version = false);
// Èíôîðìàöèÿ î ôàéëå
public function getFileLog($name);
public function getFileInfo($name);
}
// Ðåàëüíàÿ ôàéëîâàÿ ñèñòåìà
class FileSystem implements IFileSystem
{
protected $hidden = array('.', '..');
protected $visible = null;
public function __construct()
{
}
public function setVisibleFiles(array $visible)
{
$this->visible = $visible;
}
public function setHiddenFiles(array $hidden)
{
$this->hidden = array_merge($this->hidden, $hidden);
}
/**
*
*/
public function makeDirectory($name)
{
if (file_exists($name) === false) {
mkdir($name);
}
}
/**
*
*/
public function makeFile($name)
{
if (file_exists($name) === false) {
file_put_contents($name, '');
}
}
/**
*
*/
public function deleteDirectory($name)
{
rmdir($name);
}
/**
*
*/
public function deleteDirectoryRecursive($name)
{
if ($handle = opendir($name)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != "..") {
$sf = $name . DIRECTORY_SEPARATOR . $file;
if (is_dir($sf) && !is_link($sf)) {
self::deleteDirectoryRecursive($sf);
} else {
unlink($sf);
}
}
}
closedir($handle);
@rmdir($name);
}
}
/**
*
*/
public function deleteFile($name)
{
if (file_exists($name)) {
unlink($name);
}
}
// Ïðè ïåðåìåùåíèè èëè âñå ôàéëû åñëè åñòü ñîâïàäåíèÿ ïåðåïèñûâàþòñÿ
/**
*
*/
public function renameFile($source, $destination)
{
rename($source, $destination);
}
/**
*
*/
public function copyFile($source, $destination)
{
copy($source, $destination);
}
/**
*
*/
public function copyDirectory($source, $destination)
{
if (is_dir($source)) {
if (! file_exists($destination)) mkdir($destination);
$handle = opendir($source);
while (false !== ($file = readdir($handle))) {
$entry = $source . DIRECTORY_SEPARATOR . $file;
if (is_dir($entry)) {
self::copyDirectory($entry, $destination . DIRECTORY_SEPARATOR . $file);
} else {
copy($entry, $destination . DIRECTORY_SEPARATOR . $file);
}
}
}
}
/**
*
*/
public function moveUploadedFile($source, $destination)
{
move_uploaded_file($source, $destination);
}
/**
*
*/
public function isVisible($file)
{
if (in_array(basename($file), $this->hidden) === true) {
return false;
}
return ($this->isDir($file) || $this->visible == null) || in_array(pathinfo($file, PATHINFO_EXTENSION), $this->visible);
}
/**
*
*/
public function directoryFiles($name)
{
$result = array();
$files = scandir($name);
foreach ($files as $file) {
$fullname = $name . DIRECTORY_SEPARATOR . $file;
if ($this->isVisible($fullname)) {
$result [$file] = new FileRecord(array(), $fullname);
}
}
return $result;
}
/**
*
*/
public function readFile($name)
{
return file_get_contents($name);
}
/**
*
*/
public function writeFile($name, $content)
{
file_put_contents($name, $content);
}
/**
*
*/
public function directoryFilesRecursive($name)
{
}
function isDir($name)
{
return is_dir($name);
}
}
// Òî ÷òî õðàíèòñÿ â áàçå äàííûõ
class EFileSystem implements IFileSystem, IFileControl
{
protected $basepath;
protected $db;
public function __construct($basepath, $db, $fs)
{
$this->basepath = $basepath;
$this->db = $db;
$this->fs = $fs;
}
/*function createExtendRecord($index)
{
static $fileSQL = "INSERT INTO file (id_record) VALUES (?)";
$query = $this->db->prepareStatement($fileSQL);
$query->setString(1, $index);
$query->executeQuery();
}*/
private function createRecord($name, $type, $path)
{
static $recordSQL = "INSERT INTO files (filename, idfile, lastrevdate, filepath, filetype) VALUES (?, ?, ?, ?, ?)";
$last = $this->db->getIdGenerator();
$index = $last->getId('files_idfile_seq');
$query = $this->db->prepareStatement($recordSQL);
$query->setString(1, $name);
$query->setInt(2, $index);
$query->setInt(3, 0);
$query->setString(4, $path);
$query->setString(5, $type);
$query->executeQuery();
/*if ($type == 0) {
$this->createExtendRecord($index);
}*/
return $index;
}
function setVisibleFiles(array $visible)
{
$this->fs->setVisibleFiles($visible);
}
function setHiddenFiles(array $hidden)
{
$this->fs->setHiddenFiles($hidden);
}
public function getFullPath($name)
{
return Path::join($this->basepath, $name);
}
private function getRecordId($name, $path)
{
static $recordSQL = "SELECT idfile FROM files WHERE filename = ? AND filepath = ?";
$query = $this->db->prepareStatement($recordSQL);
$query->setString(1, $name);
$query->setString(2, $path);
$result = $query->executeQuery();
if ($result->next()) {
$index = $result->getInt('idfile');
return $index;
}
return false; // Ìîæåò ëó÷øå êèäàòü èñêëþ÷åíèå ??
}
function getIdFromPath($name)
{
return $this->getRecordId(basename($name), self::getPathName($name));
}
// Ñîçäàíèå íîâîé äèðåêòîðèè
public function makeDirectory($name)
{
$path = new Path($name);
$fullpath = $this->basepath;
$temp_path = '';
foreach ($path->getParts() as $subpath)
{
$index = $this->getRecordId($subpath, $temp_path);
if ($index === false) {
$index = $this->createRecord($subpath, 1, $temp_path);
}
$temp_path = Path::join($temp_path, $subpath);
}
$this->fs->makeDirectory($this->getFullPath($name));
}
public function isDir($name)
{
return $this->fs->isDir($this->getFullPath($name));
}
// Ïåðåèìåíîâàíèå ôàéëà èëè äèðåêòîðèè âñå èçìåíåíèÿ äîëæíû çàïèñûâàòüñÿ â áàçó ÷òîáû ìîæíî áûëî ñäåëàòü îòìåíó !!!
public function renameFile($source, $destination)
{
// Ïðè ïåðåìåùåíèè ôàéëû ìîãóò ñîâïàäàòü
$stmt = $this->db->prepareStatement('UPDATE files SET filepath = ?, filename = ? WHERE filepath = ? AND filename = ?');
$stmt->setString(1, self::getPathName($destination));
$stmt->setString(2, basename($destination));
$stmt->setString(3, self::getPathName($source));
$stmt->setString(4, basename($source));
$stmt->executeQuery();
if ($this->isDir($source)) {
$length = strlen($from) + 1;
$stmt = $this->db->prepareStatement("UPDATE file
SET filepath = '?' || substr(filepath, ?) WHERE filepath LIKE (?) OR filepath LIKE (? || '/%')");
$stmt->setString(1, $destination);
$stmt->setInt(2, $length);
$stmt->setString(3, $source);
$stmt->setString(4, $source);
}
$this->fs->renameFile($this->getFullPath($source), $this->getFullPath($destination));
}
// Êîïèðîâàíèå ôàéëà èëè äèðåêòîðèè
public function copyFile($source, $destination)
{
// Ïðè êîïèðîâàíèè ôàéëû ìîãóò ñîâïàäàòü
$stmt = $this->db->prepareStatement('INSERT INTO files (filepath, filename, lastrevdate) VALUES (?, ?, ?)');
$stmt->setString(1, self::getPathName($destination));
$stmt->setString(2, basename($destination));
$stmt->setString(3, time());
$stmt->executeQuery();
if ($this->isDir($source)) {
$stmt = $this->db->prepareStatement("INSERT INTO files (filepath, filename, lastrevdate)
SELECT '?' || substr(filepath, ?) AS filepath, filename, lastrevdate WHERE WHERE filepath LIKE (?) OR filepath LIKE (? || '/%')");
$stmt->setString(1, $destination);
$stmt->setInt(2, $length);
$stmt->setString(3, $source);
$stmt->setString(4, $source);
}
$this->fs->copyFile($this->getFullPath($source), $this->getFullPath($destination));
}
private function getPathName($name)
{
$path = dirname($name);
return ($path == '.') ? '' : $path;
}
public function makeFile($name)
{
$base = self::getPathName($name);
$this->makeDirectory($base);
$filename = basename($name);
$index = $this->getRecordId($filename, $base);
if ($index === false) {
$index = $this->createRecord($filename, 0, $base);
}
$this->fs->makeFile($this->getFullPath($name));
}
public function readFile($name)
{
return $this->fs->readFile($this->getFullPath($name));
}
public function readFileVersion($name, $revision = false)
{
if ($revision === false) {
return $this->readFile($name);
} else {
$id_file = $this->getIdFromPath($name);
$query = $this->db->prepareStatement("SELECT * FROM history WHERE revision = ? AND idfile = ?");
$query->setInt(1, $revision);
$query->setInt(2, $id_file);
$file = $query->executeQuery();
if ($file->next()) {
return gzuncompress($file->getBlob('content'));
}
}
return null;
}
public function writeFile($name, $content)
{
$this->makeFile($name);
$this->fs->writeFile($this->getFullPath($name), $content);
}
public function getLastRevision($name)
{
$id_file = $this->getIdFromPath($name);
$stmt = $this->db->prepareStatement("SELECT * FROM history WHERE revision IN (SELECT MAX(revision) AS lastrev FROM history WHERE idfile = ?)");
$stmt->setInt(1, $id_file);
$rev = $stmt->executeQuery();
if ($rev->next()) {
return $rev;
}
return false;
}
/**
*
*/
public function commitFile($name, $owner, $message)
{
$id_file = $this->getIdFromPath($name);
$content = $this->readFile($name);
$stmt = $this->db->prepareStatement("SELECT MAX(revision) AS lastrev FROM history WHERE idfile = ?");
$stmt->setInt(1, $id_file);
$rev = $stmt->executeQuery();
$revision = ($rev->next()) ? $rev->getInt('lastrev') + 1 : 1;
$query = $this->db->prepareStatement("INSERT INTO history (content, owner, revsummary, revdate, revision, idfile) VALUES (?, ?, ?, ?, ?, ?)");
$query->setBlob(1, gzcompress($content));
$query->setString(2, $owner);
$query->setString(3, $message);
$query->setInt(4, time());
$query->setInt(5, $revision);
$query->setInt(6, $id_file);
$query->executeQuery();
}
/**
*
*/
public function getFileDifference($name, $revision1, $revision2 = false)
{
$first = $this->readFileVersion($name, $revision1);
$second = $this->readFileVersion($name, $revision2);
}
/**
*
*/
public function getFileLog($name)
{
$id_file = $this->getIdFromPath($name);
$query = $this->db->prepareStatement("SELECT revision,revsummary,owner,revdate FROM history WHERE idfile = ? ORDER BY revision");
$query->setInt(1, $id_file);
$list = $query->executeQuery();
return iterator_to_array($list->getIterator());
}
public function directoryFiles($name)
{
$result = $this->fs->directoryFiles($this->getFullPath($name));
/* Ñïèñîê ôàéëîâ èç áàçû äàííûõ */
$query = $this->db->prepareStatement("SELECT * FROM files WHERE filepath = ?");
$query->setString(1, $name);
$list = $query->executeQuery();
foreach ($list as $file) {
$fullpath = $this->getFullPath($name . DIRECTORY_SEPARATOR . $file['filename']);
if ($this->fs->isVisible($fullpath)) {
$file['state'] =
((isset($result[$file['filename']])) ?
(($file['lastrevdate'] > $file['change']) ? 'exclamation' : 'unchanged')
: 'expected');
$record = new FileRecord($file, $fullpath);
$result [$file['filename']] = $record;
}
}
return $result;
}
public function getFileInfo($name)
{
$index = $this->getIdFromPath($name);
$fullpath = $this->basepath . DIRECTORY_SEPARATOR . $name;
if ($index !== false) {
$query = $this->db->prepareStatement("SELECT * FROM files AS r LEFT JOIN filemeta AS f ON r.idfile = f.id_record WHERE r.idfile = ?");
$query->setInt(1, $index);
$list = $query->executeQuery();
$list->next();
$file = $list->getRow();
$file['state'] = (file_exists($fullpath) ? 'unchanged' : 'expected');
$result = new FileRecord($file, $fullpath);
} else {
$result = new FileRecord(array(), $fullpath);
}
return $result;
}
public function setFileInfo($name, Collection $list)
{
$index = $this->getIdFromPath($name);
if ($index !== false) {
$stmt = $this->db->prepareStatement("UPDATE files SET title = ? WHERE idfile = ?");
$stmt->setString(1, $list->get('title'));
$stmt->setInt(2, $index);
$stmt->executeQuery();
/*if (some($list, array('keywords', 'author', 'description'))) {
$hasfile = $this->db->executeQuery("SELECT * FROM file WHERE id_record = $index");
if(!$hasfile->next()) {
static $fileSQL = "INSERT INTO file (id_record) VALUES (?)";
$query = $this->db->prepareStatement($fileSQL);
$query->setString(1, $index);
$query->executeQuery();
}
$query = $this->db->prepareStatement("UPDATE file SET keywords = ?, author = ?, description = ? WHERE id_record = ?");
$query->setString(1, $list->get('keywords'));
$query->setString(2, $list->get('author'));
$query->setString(3, $list->get('description'));
$query->setInt(4, $index);
$query->executeQuery();
}*/
}
}
/**
* Óäàëÿåì äèðåêòîðèþ åñëè îíà íå ïóñòàÿ
*/
function deleteDirectory($name)
{
$index = $this->getIdFromPath($name);
$query = $this->db->prepareStatement("SELECT COUNT(*) AS col FROM files WHERE filepath = (?) OR filepath LIKE(? || '/%')");
$query->setString(1, $name);
$query->setString(2, $name);
$result = $query->executeQuery();
$result->next();
if ($index && $result->getInt('col') == 0) {
$query = $this->db->prepareStatement("DELETE FROM files WHERE idfile = ?");
$query->setInt(1, $index);
$query->executeQuery();
}
$this->fs->deleteDirectory($this->getFullPath($name));
}
function deleteFile($name)
{
$index = $this->getIdFromPath($name);
if ($index) {
$query = $this->db->prepareStatement("DELETE FROM history WHERE idfile = ?;
DELETE FROM filemeta WHERE id_record = ?;DELETE FROM files WHERE idfile = ?");
$query->setInt(1, $index);
$query->setInt(2, $index);
$query->setInt(3, $index);
$query->executeQuery();
}
$this->fs->deleteFile($this->getFullPath($name));
}
function moveUploadedFile($source, $destination)
{
$this->fs->moveUploadedFile($source, $this->getFullPath($destination));
$this->makeFile($destination);
}
function directoryFilesRecursive($name)
{
$files = $this->fs->directoryFilesRecursive($this->getFullPath($name));
$query = $this->db->prepareStatement("DELETE FROM files WHERE filepath = (?) OR filepath LIKE (? || '/%')");
$query->setString(1, $name);
$query->setString(2, $name);
$query->executeQuery();
}
}

View file

@ -0,0 +1,34 @@
<?php
/**
* Ôèëüòð äåéñòâèé
*/
class ActionAccess
{
public $access = array();
function __construct($processor)
{
$this->processor = $processor;
}
/**
* Ïðîâåðêà äîñòóïíûõ äåéñòâèé äëÿ ïîëüçîâàòåëÿ
* !! Ðåàëèçàöèÿ êëàññà ïðîâåðêè äåéñòâèé íå äîëæíà áûòü âíóòðè Êîíòðîëëåðà!!!
* Èíôîðìàöèÿ î äîñòóïå ìîæåò áûòü â ôàéëå, áàçå äàííûõ è ò.ä.
*/
function checkAction($action)
{
// Èìïëèêàöèÿ !! http://ru.wikipedia.org/wiki/Èìïëèêàöèÿ
return (!isset($this->access[$action]) || in_array(UserAccess::$access, $this->access[$action]));
}
function execute(HTTPRequest $request)
{
$action = $request->getAction();
if(! $this->checkAction($action)) {
$request->set('action', 'index');
}
return $this->processor->execute($request);
}
}

View file

@ -0,0 +1,26 @@
<?php
require_once 'core/path.php';
class ActionLogger
{
public $before = array ();
public $file;
public $action;
public $processor;
function __construct($processor)
{
$this->processor = $processor;
$this->file = fopen(Shortcut::getUrl('access.log'), "a");
}
function execute(HTTPRequest $request)
{
$action = $request->getAction();
if(in_array($action, $this->before)) {
fwrite($this->file, "time: " . date("r", time()) . " query: ". json::encode(array_merge($_POST, $_GET)) . " by: " . UserAccess::$name . "\n");
}
return $this->processor->execute($request);
}
}

72
core/filter/filter.php Normal file
View file

@ -0,0 +1,72 @@
<?php
require_once 'filterbase.php';
require_once 'filterlogin.php';
// Êëàññ äîëæåí áûòü â áèáëèîòåêå ïðèëîæåíèÿ
class UserAccess
{
const LIFE_TIME = 1800; // = 30min * 60sec;
static $fullname;
static $name;
static $access;
static $password;
static $id;
static $db;
protected function __construct()
{
}
public static function setUp($db)
{
self::$db = $db;
}
public static function getUserByQuery($stmt)
{
global $GROUPS;
$result = $stmt->executeQuery();
if ($result->next()) {
self::$access = $GROUPS[$result->getString('access')];
self::$name = $result->getString('login');
self::$id = $result->getInt('id_user');
self::$password = $result->getString('password');
self::$fullname = implode(' ', array(
$result->getString('surname'),
$result->getString('firstname'),
$result->getString('patronymic')));
return $result;
}
return null;
}
public static function getUserByLogin($login)
{
$stmt = self::$db->prepareStatement("SELECT * FROM users WHERE login = ?");
$stmt->setString(1, $login);
$result = self::getUserByQuery($stmt);
if ($result) {
$time = time();
$id = self::$id;
self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Âðåìÿ âõîäà
}
return $result;
}
public static function getUserById($id)
{
$stmt = self::$db->prepareStatement("SELECT * FROM users WHERE id_user = ?");
$stmt->setInt(1, $_SESSION ['access']);
$result = self::getUserByQuery($stmt);
if ($result) {
$lasttime = $result->getInt('lasttime');
$time = time();
if ($time - $lasttime > self::LIFE_TIME) return null; // Âûøëî âðåìÿ ñåññèè
$id = self::$id;
$stmt = self::$db->executeQuery("UPDATE users SET lasttime = $time WHERE id_user = $id"); // Âðåìÿ ïîñëåäíåãî îáðàùåíèÿ âõîäà
}
return $result;
}
}

View file

@ -0,0 +1,28 @@
<?php
/**
* Ïîïûòêà ðåàëèçîâàòü ôèëüòð äëÿ çàïðîñîâ
*/
class Filter
{
public $processor;
public function __construct($processor)
{
$this->processor = $processor;
}
public function execute(Collection $request)
{
return $this->processor->execute($request);
}
public function getView($name)
{
return $this->processor->getView($name);
}
public function getConnection()
{
return $this->processor->getConnection();
}
}

105
core/filter/filterlogin.php Normal file
View file

@ -0,0 +1,105 @@
<?php
/**
* Ôèëüòð äëÿ ïðîâåðêè àâòîðèçàöèè
*
* action: login(password, login)
* action: logout()
*/
// Â êëàññ àâòîðèçàöèè ïåðåäàâàòü îáüåêò äëÿ óïðàâëåíèÿ ïîëüçîâàòåëåì
// Âûíåñòè â îòäåëüíûé ôàéë
class LoginFilter extends Filter
{
const SESSION_BROWSER_SIGN_SECRET = '@w3dsju45Msk#';
const SESSION_BROWSER_SIGN_KEYNAME = 'session.app.browser.sign';
public $mode = 'ajax';
/**
* Ïðîâåðêà àâòîðèçàöèè
* @return Boolean Àâòîðèçîâàíè ïîëüçîâàòåëü èëè íåò
*/
public function isLoggin(Collection $request)
{
// Àâòîðèçàöèÿ
session_start();
$db = $this->getConnection();
UserAccess::setUp($db); // Ñîåäèíåíèå
switch ($request->getAction()) {
// Àâòîðèçàöèÿ ïî ïîñòîÿííîìó ïàðîëþ
case 'login':
$login = $request->get('login');
$password = $request->get('password');
$result = UserAccess::getUserByLogin($login); // Ïîèñê ïî ëîãèíó
if ($result) {
if (md5($password) == $result->getString('password')) { // password
$this->enter($db, $result);
return true;
}
}
$request->set('error', true);
break;
case 'logout': // Âûõîä
session_destroy();
break;
// Âõîä ïî âðåìåííîìó ïàðîëþ
case 'enter':
$login = $request->get('login');
$password = $request->get('sid');
$result = UserAccess::getUserByLogin($login); // Ïîèñê ïî ëîãèíó
if ($result) {
$temp = md5($result->getString('password') . $result->getString('login') . $result->getString('sid'));
if ($password == $temp) {
$this->enter($db, $result);
return true;
}
}
break;
default:
$hash = $this->getBrowserSign();
// Åñëè $hash íå ñîâïàäàåò $_SESSION['hash'] òî óäàëÿåì ñåññèþ
if (isset($_SESSION ['access']) && isset($_SESSION[self::SESSION_BROWSER_SIGN_SECRET])) {
if ($hash == $_SESSION[self::SESSION_BROWSER_SIGN_SECRET]) {
UserAccess::getUserById($_SESSION ['access']); // Ïîèñê ïî èäåíòèôèêàòîðó
return true;
} else {
session_destroy();
}
}
}
return false;
}
private function getBrowserSign()
{
$rawSign = self::SESSION_BROWSER_SIGN_SECRET;
$signParts = array('HTTP_USER_AGENT', 'HTTP_ACCEPT_ENCODING');
$rawSign = '';
foreach ($signParts as $signPart) {
$rawSign .= '::' . (isset($_SERVER[$signPart]) ? $_SERVER[$signPart] : 'none');
}
return md5($rawSign);
}
private function enter($db, $result)
{
$db->executeQuery("UPDATE users SET sid = '' WHERE id_user = " . $result->getInt('id_user'));
$_SESSION ["group"] = $result->getInt('access');
$_SESSION ["access"] = $result->getInt('id_user'); // id_user
$_SESSION [self::SESSION_BROWSER_SIGN_SECRET] = $this->getBrowserSign();
$_SESSION ["time"] = time();
}
public function execute(Collection $request)
{
if (!$this->isLoggin($request)) {
// Ïàðàìåòðû ïðè íåïðàâèëüíîé àâòîðèçàöèè
// Äåéñòâèÿ ïî óìîë÷àíèþ !! Âîçìîæíî ïåðåõîä íà ôîðìó ðåãèñòðàöèè
$request->set('module', 'login');
$request->set('mode', $this->mode);
}
return $this->processor->execute($request);
}
}

335
core/form.php Normal file
View file

@ -0,0 +1,335 @@
<?php
/**
* Deprecated !!!!
*/
require_once 'core/adapter.php';
/**
* Íîâîå API äëÿ Ôîðì
* $form = new Form ();
* $form->render () -> html,
* $form->adjust ($scheme);
* $form->input ($name, $type, $label, );
* $form->set($name, $value);
* $form->get($name); -> value
* $form->parse ($request),
* $form->validate () -> boolean,
* $form->values () -> pair[key] = value
*/
/**
* Ýëåìåíò ôîðìû
* @package core
*/
class TField {
protected $_value; // Ôîðìàòèðîâàííîå çíà÷åíèå ïîëÿ
var $label; // Ìåòêà ïîëÿ
var $rule = array ();// Ïðàâèëà äëÿ ïðîâåðêè ïîëÿ
var $value; // Ôîðìàòèðîâàííîå Çíà÷åíèå ïîëÿ
// var $default; // Çíà÷åíèå ïî óìîë÷àíèþ
var $error = false; // â XRule Ïðàâèëà äëÿ ïðîâåðêè çíà÷åíèé
var $error_msg = "Ïîëå íå ìîæåò áûòü ïóñòûì";
var $type; // Êàæäîìó òèïó ýëåìåíòà ñîîòâåòñòâóåò ìàêðîñ TAL
public function __construct ($input) {
// $this->deafult = null;
$this->require = false;
// Èíèöèàëèçàöèÿ ñâîéñò îáüåòêà
foreach ($input as $key => $value) {
$this->$key = $value;
}
}
public function __toString () {
return $this->value;
}
public function isValid ($name) {
if ($this->require == true && empty($this->value)) {
$this->error = true;
return false;
}
$this->setValue ($this->value);
return true;
}
// Äîáàâèòü ìåòîäû getString, setString ??
function setValue ($value) {
$this->_value = $value;
$this->value = $value;
}
function getValue () {
return $this->_value;
}
}
/**
* Ïîëå ââîäà Input
* @package core
*/
class TInput extends TField {
public function __construct ($input) {
parent::__construct ($input);
$this->setValue ("");
}
}
// checkbox
class TCheckbox extends TField {
public $checked = false;
public function __construct ($input) {
parent::__construct ($input);
$this->setValue (1);
}
function setValue ($value) {
$this->_value = intval ($value);
$this->value = 1;
if ($this->_value == 1) $this->checked = true; else $this->checked = false;
}
}
/**
* Âûáîð èç îäíîãî ýëåìåíòà
*/
class TSelect1 extends TField {
var $options = array ();
public function __construct ($input) {
parent::__construct ($input);
$this->setValue (0);
}
function setValue ($value) {
$this->_value = $value;
$this->value = $value;
foreach ($this->options as $key => $o) {
$this->options[$key]['selected'] = ($this->options[$key]['value'] == $this->_value);
}
}
}
class TSelectGroup extends TField {
var $groups = array ();
public function __construct ($input) {
parent::__construct ($input);
$this->setValue (0);
}
function setValue ($value) {
$this->_value = $value;
$this->value = $value;
foreach ($this->groups as $gkey => $o) {
foreach ($this->groups[$gkey]['options'] as $key => $v) {
$this->groups[$gkey]['options'][$key]['selected'] = ($this->groups[$gkey]['options'][$key]['value'] == $this->_value);
}
}
}
}
/**
* Ïîëå ñ äàòîé
* @package core
*/
class TDate extends TField {
var $error_msg = "Íåâåðíûé ôîðìàò äàòû";
var $separator = ".";
public function __construct ($input) {
parent::__construct ($input);
$this->setValue (time ());
}
function isValid ($name) {
$value = $this->value;
if ($tmp = explode(".", $value, 3)) {
if ($tmp[1] && $tmp[0] && $tmp[2]) {
if (checkdate ($tmp[1], $tmp[0], $tmp[2])) {
$this->setValue (mktime (0, 0, 0, $tmp[1], $tmp[0], $tmp[2]));
return true;
}
}
}
$this->error = true;
return false;
}
function setValue ($value) {
$this->_value = $value;
$this->value = date ("d.m.Y", $value);
}
}
class TTime extends TField {
var $error_msg = "Íåâåðíûé ôîðìàò âðåìåíè";
public function __construct ($input) {
parent::__construct ($input);
$this->setValue (mktime(0, 0, 0, 11, 30, 1999));
}
function isValid ($name) {
$value = $this->value;
if ($tmp = explode(":", $value, 2)) {
if ($this->checktime ($tmp[0], $tmp[1])) {
$this->setValue (mktime ($tmp[0], $tmp[1], 0, 0, 0, 0));
return true;
}
}
$this->error = true;
return false;
}
function checktime($hour, $minute) {
if ($hour > -1 && $hour < 24 && $minute > -1 && $minute < 60) {
return true;
}
}
function setValue ($value) {
$this->_value = $value;
$this->value = date ("H:i", $value);
}
}
/* *
* Òåêñòîâîå ïîëå
* @package core
*/
class TTextArea extends TField {
public function __construct ($input) {
parent::__construct ($input);
$this->setValue ("");
}
}
/**
* Ïîëå äëÿ ââîäà ïàðîëÿ
* @package core
*/
class TSecret extends TField {
public function __construct ($input) {
parent::__construct ($input);
$this->setValue ("");
}
}
class TUpload extends TField {
public $types = array ();
public function __construct ($input) {
parent::__construct ($input);
$this->setValue ("");
}
public function setValue ($value) {
$this->_value = basename ($value);
$this->value = $value;
}
}
/**
* Ôîðìà äëÿ ââîäà
* @package core
*/
class TForm {
var $field = array ();
var $action = "";
var $method = 'post';
var $request;
var $replace;
public function __construct ($request) {
$this->uid = get_form_uid ();
$this->constructor = array (
'input' => 'TInput',
'checkbox' => 'TCheckbox',
'date' => 'TDate',
'time' => 'TTime',
'textarea' => 'TTextArea',
'select' => 'TSelect',
'select1' => 'TSelect1',
'selgroup' => 'TSelectGroup',
'secret' => 'TSecret',
'upload' => 'TUpload'
);
$this->request = $request;
}
function get ($name) {
return $this->field [$name]->getValue ();
}
function addFieldObject ($name, $el) {
$this->field [$name] = $el;
}
/**
* Ìåòîä äîëæåí ïðîâåðÿòü çíà÷åíèÿ ïîëåé ôîðìû ïîëñëå çàïîëíåíèÿ
* Ïðîâåðêà ïðàâèëüíîñòè çàïîëíåíèÿ ôîðìû è óñòàíîâêà çíà÷åíèé
*/
function isValid () {
$haveErrors = false;
foreach ($this->field as $name => $el) { // ññûëêà
if ($this->field [$name] instanceof TUpload) {
// print_r ($_POST);
$filename = $this->request->getRawData ('files', $name);
if ((bool) $filename['name']) {
$this->field [$name]->value = $filename['name'];
} else {
$this->field [$name]->value = $this->request->getRawData ($this->method, $name."_file");
}
} else {
$this->field [$name]->value = $this->request->getRawData ($this->method, $name);
}
if (!$this->field [$name]->isValid($name)) {
$haveErrors = true;
}
}
return !$haveErrors;
}
/**
* Äîáàâëÿåò îäíî ïîëå ââîäà íà ôîðìó
*/
public function addField ($init) {
assert ($init['type']);
assert ($init['name']);
$constructor = $this->constructor[$init['type']];
$el = new $constructor ($init);
$el->type = $init['type'];
$this->addFieldObject ($init['name'], $el);
return $el;
}
/**
* Äîáàâëÿåò ñïñîê ïîëåé äëÿ ôîðìû
* @param array $list
*/
public function addFieldList ($list) {
foreach ($list as $init) {
$this->addField ($init);
}
}
/**
* Çàïîëíÿåò ôîðìó äàííûìè èç êîëëåêöèè
* Äëÿ îáüåêòîâ è ìàññèâîâ ìîæíî èñïîëüçîâàòü Adapter pattern
* @param object $data
* @param array $schema Ñâÿçü ìåæäó ýëåìåíòàìè ôîðìû è ñâîéñòâàìè îáüåêòà
*/
public function fill ($data) {
foreach ($this->field as $name => $el) {
$this->field [$name]->setValue ($data->get ($name));
}
}
}
?>

180
core/form/form.php Normal file
View file

@ -0,0 +1,180 @@
<?php
/**
* Ýëåìåíò ôîðìû
* @package core
*/
class TField
{
public $name;
public $label; // Ìåòêà ïîëÿ
public $value; // Çíà÷åíèå ïîëÿ
public $type; // Êàæäîìó òèïó ýëåìåíòà ñîîòâåòñòâóåò ìàêðîñ TAL
public $error_msg = null;
public $error = false;
public $require = false;
public function __construct ($input)
{
$this->deafult = null;
if (isset($input['validate'])) {
$this->require = strpos($input['validate'], 'require') !== false;
}
// Èíèöèàëèçàöèÿ ñâîéñò îáüåòêà
foreach (array('label', 'name', 'type') as $name) {
$this->$name = $input[$name];
}
}
function setValue($value)
{
$this->value = $value;
}
}
/**
* Ïîëå ââîäà Input
* @package core
*/
class TInput extends TField {
}
/**
* Âûáîð èç îäíîãî ýëåìåíòà
*/
class TSelect1 extends TField
{
public $options = array ();
public function __construct ($input) {
parent::__construct($input);
$this->options = $input['options'];
}
function setValue($value)
{
// Óñòàíîâèòü selected ó options
$this->value = $value;
}
}
/**
* Ïîëå ñ äàòîé
* @package core
*/
class TDate extends TField
{
}
/* *
* Òåêñòîâîå ïîëå
* @package core
*/
class TTextArea extends TField
{
}
/**
* Ïîëå äëÿ ââîäà ïàðîëÿ
* @package core
*/
class TSecret extends TField
{
}
class TUpload extends TField
{
}
/**
* Ôîðìà äëÿ ââîäà
* @package core
*/
class TForm
{
public $field = array ();
public $action = "";
public $method = 'post';
protected $replace;
protected $before;
public function __construct ()
{
$this->constructor = array (
'input' => 'TInput',
'date' => 'TDate',
'textarea' => 'TTextArea',
'select' => 'TSelect',
'select1' => 'TSelect1',
'secret' => 'TSecret',
'upload' => 'TUpload'
);
}
/**
* Äîáàâëÿåò îäíî ïîëå ââîäà íà ôîðìó
*/
public function addField (array $init)
{
assert (isset($init['type']));
assert (isset($init['name']));
$constructor = $this->constructor[$init['type']];
$el = new $constructor ($init);
$el->type = $init['type'];
$this->field [$init['name']] = $el;
return $el;
}
/**
* Äîáàâëÿåò ñïñîê ïîëåé äëÿ ôîðìû
* @param array $list
*/
public function addFieldList (array $list)
{
foreach ($list as $init) {
$this->addField ($init);
}
}
/**
* Óñòàíàâëèâàåò îøèáêè ïîñëå ïðîâåðêè
*/
function setError (Validator $validator)
{
foreach ($validator->getErrorMsg() as $name => $error)
{
$this->field[$name]->error = true;
$this->field[$name]->error_msg = $error;
}
}
/**
* Óñòàíàâëèâàåò çíà÷åíèÿ èç ìàñèâà
*/
function setValues (Collection $request) {
foreach ($this->field as $key => $el) {
$value = $request->getRawData ($this->method, $key);
$this->field[$key]->setValue($value);
}
}
/**
* Çàïîëíÿåò ôîðìó äàííûìè èç îáüåêòà
* @param object $data
* @param array $schema Ñâÿçü ìåæäó ýëåìåíòàìè ôîðìû è ñâîéñòâàìè îáüåêòà
*/
public function fill ($data, array $schema)
{
foreach ($schema as $key => $value) {
$this->field [$value]->setValue($data->$value->getString ());
}
}
public function set($name, $value)
{
$this->field[$name]->setValue($value);
}
}
?>

43
core/form/viewstate.php Normal file
View file

@ -0,0 +1,43 @@
<?php
/**
* http://www.alternateinterior.com/2006/09/a-viewstate-for-php.html
* Óïðàâëåíèå ñîñòîÿíèåì ìåæäó ñòðàíèöàìè
*/
class ViewState // extends Collection
{
private $values = array();
function set($name, $value)
{
$this->values[$name] = $value;
}
function get()
{
$args = func_get_args();
$result = $this->values;
foreach ($args as $name) {
if (!isset($result[$name])) {
return null;
}
$result = $result[$name];
}
return $result;
}
function saveState()
{
return base64_encode(serialize($this->values));
}
function restoreState($value)
{
$this->values = unserialize(base64_decode($value));
}
function export()
{
return $this->values;
}
}

52
core/formats/dot.php Normal file
View file

@ -0,0 +1,52 @@
<?php
/**
* Ãåíåðàöèÿ ôàéëîâ Grpahviz dot
*/
class Dot
{
static function getHeader ()
{
$header =
"digraph G {\n"
. "\toverlap=false; splines=true;\n"
. "\tfontname = \"Verdana\"\n"
. "\tfontsize = 8\n"
. "\tnode [\n"
. "\t\tfontname = \"Verdana\"\n"
. "\t\tfontsize = 8\n"
. "\t\tshape = \"record\"\n"
. "\t]\n"
. "\tedge [\n"
. "\t\tfontname = \"Verdana\"\n"
. "\t\tfontsize = 8\n"
. "\t]\n";
return $header;
}
static function getFooter ()
{
$footer = "}\n";
return $footer;
}
function assocToDot (array $array, array $label)
{
$result = array (self::getHeader());
// Ìåòêè
foreach ($label as $value) {
$result [] = "\t\"{$value[0]}\" [ label = \"{$value[1]}\" ] \n";
}
// Àññîöèàöèè
foreach ($array as $key => $value) {
foreach ($value as $n) {
$result [] = "\t\"$key\" -> \"$n\"\n";
}
}
$result [] = self::getFooter();
return implode("", $result);
}
}
?>

86
core/formats/helix.php Normal file
View file

@ -0,0 +1,86 @@
<?php
define ('URL_CLIP', 0);
define ('URL_DIRECTORY', 1);
class HAuthorize {
public $password;
public $uuid;
public $uuid_writeable;
public function __construct () {
$this->uuid = "*";
$this->uuid_writeable = 1;
}
public function getString () {
return "{$this->password};{$this->uuid};{$this->uuid_writeable}";
}
public function setPassword ($username, $realm, $password) {
$this->password = md5 ("$username:$realm:$password");
}
}
class HPermission {
public $url;
public $url_type;
public $permission_type;
public $expires;
public $debitted_time;
public function __construct ($url, $url_type) {
$this->url = $url;
$this->url_type = $url_type;
$this->expires = "*"; // MM/DD/YYYY:HH:MM:SS
$this->permission_type = 0;
$this->debitted_time = 0;
}
public function getString () {
return "{$this->url};{$this->url_type};{$this->permission_type};{$this->expires};{$this->debitted_time}";
}
}
class HFile {
public $authorize;
public $permission = array ();
public function addAuthorize ($name, $realm, $password) {
$this->authorize = new HAuthorize ();
$this->authorize->setPassword ($name, $realm, $password);
}
public function addPermission ($url, $url_type) {
$this->permission[] = new HPermission ($url, $url_type);
}
public function write ($name) {
$file = fopen ($name, 'w');
fwrite ($file, $this->getString ());
fclose ($file);
}
public function writeFTP ($ftp, $path) {
$file = tmpfile ();
fwrite ($file, $this->getString ());
fseek ($file, 0);
ftp_fput ($ftp, $path, $file, FTP_BINARY);
fclose ($file);
}
public function getString () {
$result = array ();
$result[] = $this->authorize->getString ();
$result[] = "\n";
foreach ($this->permission as $p) {
$result[] = $p->getString ();
$result[] = "\n";
}
return implode ("", $result);
}
}
?>

346
core/functions.php Normal file
View file

@ -0,0 +1,346 @@
<?php
/**
* Ôóíêöèîíàëüíîå ïðîãðàììèðîâàíèå â PHP
* package functional
*/
/**
* Ýìóëÿöèÿ êàððèðîâàíîé ôóíêöèè
*/
class __right {
protected $params;
protected $fn;
public function __construct($params) {
$this->fn = array_shift($params);
$this->params = $params;
}
function apply() {
$params = func_get_args();
array_splice($params, count($params), 0, $this->params);
return call_user_func_array($this->fn, $params);
}
}
class __left {
protected $params;
protected $fn;
public function __construct($params) {
$this->fn = array_shift($params);
$this->params = $params;
}
function apply() {
$params = func_get_args();
array_splice ($params, 0, 0, $this->params);
return call_user_func_array ($this->fn, $params);
}
}
define('__', '_ARGUMENT_PLACE_');
class __partial {
protected $params;
protected $fn;
public function __construct($params) {
$this->fn = array_shift($params);
$this->params = $params;
}
function apply() {
$params = func_get_args();
$result = array();
for($i = 0, $j = 0; $i < count($this->params); $i++) {
if ($this->params[$i] == __) {
$result [] = $params[$j];
$j++;
} else {
$result [] = $this->params[$i];
}
}
return call_user_func_array ($this->fn, $result);
}
}
function partial() {
$closure = new __partial(func_get_args());
return array($closure, 'apply');
}
/**
* Êîìïîçèöèÿ ôóíêöèé
*/
class __compose {
protected $fns;
function __construct($list) {
$this->fns = array_reverse($list);
}
function apply () {
$params = func_get_args ();
$result = call_user_func_array($this->fns[0], $params);
for ($i = 1; $i < count($this->fns); $i++) {
$result = call_user_func($this->fns[$i], $result);
}
return $result;
}
}
/**
* Êîìïîçèöèÿ ôóíêöèé
* @param mixed $a
* @param mixed $b
*
* @return array[int]mixed
*/
function compose() {
$closure = new __compose(func_get_args());
return array($closure, 'apply');
}
/**
* Êàðèðîâàíèå ñïðàâà
*
* @return array[int]mixed
*/
function rcurry() {
$closure = new __right(func_get_args ());
return array($closure, 'apply');
}
/**
* Êàðèðîâàíèå ñëåâà
*
* @return array[int]mixed
*/
function lcurry() {
$closure = new __left(func_get_args ());
return array($closure, 'apply');
}
/**
* Ðàçäåëåíèå ìàññèâà íà äâà ïî óñëîâèþ
* @param mixed $pred Óñëîâèå ïî êîòîðîìó ðàçäåëÿåòñÿ ìàññèâ
* @param array $lst
*
* @return array[int]mixed
*/
function partition($pred, $lst) {
$left = array ();
$right = array ();
foreach ($lst as $n) {
if (call_user_func($pred, $n) !== false) {
$left [] = $n;
} else {
$right [] = $n;
}
}
return array ($left, $right);
}
/**
* @param array $value
* @param string $name
*
* @return mixed
*/
function __key($value, $name) {
return $value[$name];
}
function identity($value) {
return $value;
}
/**
* @param array $a
* @param array $b
* @param $key
*
* @return int
*/
function __cmp($a, $b, $key) {
if ($a[$key] == $b[$key]) {
return 0;
}
return ($a[$key] > $b[$key]) ? -1 : 1;
}
function __cmp_less($a, $b, $key) {
if ($a[$key] == $b[$key]) {
return 0;
}
return ($a[$key] < $b[$key]) ? -1 : 1;
}
// Ñðàâíåíèå ïî êëþ÷ó ìàññèâå
function __index($n, $key, $row) {
return ($row[$key] == $n);
}
function __div($x, $y) {
return $x / $y;
}
function __self($name, $o) {
return call_user_func(array($o, $name));
}
function concat(/* $args ...*/) {
$args = func_get_args();
return implode($args);
}
function __empty($x) {
return empty($x);
}
// Îòðèöàíèå
function __not($x) {
return !$x;
}
// Íå ðàâíî
function __neq($x, $y) {
return $x != $y;
}
// Ðàâíî
function __eq($x, $y) {
return $x == $y;
}
/**
* Èçâëåêàåò èç ìíîãîìåðîãî ìàññèâà çíà÷åíèÿ ñ îïðåäåëåííûì êëþ÷îì
* @example key_values('a', array(1 => array('a' => 1, 'b' => 2))) => array(1)
*
* @return mixed
*/
function key_values($key, /*array|ArrayIterator*/ $array) {
$result = array();
foreach($array as $item) {
$result[] = $item[$key];
}
return $result;
}
function assoc_key_values($key, $value, $array) {
$result = array();
foreach ($array as $item) {
$result[$item[$key]] = $item[$value];
}
return $result;
}
function assoc_key($key, $array) {
$result = array();
foreach ($array as $item) {
$result[$item[$key]] = $item;
}
return $result;
}
function _get($key, $value, $array) {
foreach ($array as $item) {
if ($item[$key] == $value) return $item;
}
return null;
}
function _get_key($key, $value, $array) {
foreach ($array as $name => $item) {
if ($item[$key] == $value) return $name;
}
return null;
}
/**
* Ëîãè÷åñêà îïåðàöèÿ && êî âñåì ýëåìåíòàì ìàññèâà
* @return bool
*/
function every(array $array, $callback) {
foreach ($array as $key => $value) {
if (call_user_func($callback, $value) === false) {
return false;
}
}
return true;
}
/**
* Ëîãè÷åñêà îïåðàöèÿ || êî âñåì ýëåìåíòàì ìàññèâà
* @param array $array
* @param mixed $callback
*
* @return mixed
*/
function some(array $array, $callback) {
assert(is_callable($callback));
foreach ($array as $key => $value) {
if (call_user_func($callback, $value) === true) {
return $key;
}
}
return false;
}
function span($length, array $array) {
assert(is_int($length));
$result = array();
for($i = 0; $i < count($array); $i += $length) {
$result [] = array_slice($array, $i, $length);
}
return $result;
}
function array_ref($data, $n) {
return $data[$n];
}
function call() {
$args = func_get_args();
$name = array_shift($args);
return call_user_func_array($name, $args);
}
/**
* Ïîèñê ýëåìåíòà â ìàññèâå
* @param function $cb ñðàâíåíèå ñ ýëåìåíòîì ìàññèâà
* @param array $hs ìàññèâ â êîòîðîì èùåòñÿ çíà÷åíèå
*
* @return int|string êëþ÷ íàéäåíîãî ýëåìåíòà â ìàññèâå
*/
function array_usearch($cb, array $hs, $strict = false) {
foreach($hs as $key => $value) if (call_user_func_array($cb, array($value, $key, $strict))) return $key;
}
if (!function_exists('hash_key')) {
/**
* Ïðåîáðàçóåò êëþ÷è ýëåìåíòîâ äëÿ ìíîãîìåðíîãî ìàññèâà
* @return mixed
*/
function hash_key ($key_name,/*. array .*/ $array) {
$result = array();
foreach($array as $value) {
$result[$value[$key_name]] = $value;
}
return $result;
};
}
function array_merge1($x, $y) {
$result = $x;
foreach ($y as $k => $v) {
$result [$k] = $v;
}
return $result;
}

13
core/geometry/point.php Normal file
View file

@ -0,0 +1,13 @@
<?php
class Point
{
public $left, $top;
function __construct ($left = 0, $top = 0)
{
$this->left = $left;
$this->top = $top;
}
}
?>

View file

@ -0,0 +1,53 @@
<?php
require_once "core/geometry/point.php";
class Rectangle
{
public $left, $top, $width, $height;
function __construct($left = 0, $top = 0, $width = 0, $height = 0)
{
$this->left = $left;
$this->top = $top;
$this->width = $width;
$this->height = $height;
}
function __get($name)
{
switch ($name) {
case 'right': return $this->left + $this->width;
case 'bottom': return $this->top + $this->height;
}
}
function __set($name, $value)
{
switch ($name) {
case 'right': $this->width = $value - $this->left;
case 'bottom': $this->height = $value - $this->top;
}
}
/**
* Ñìåùàåò ïðÿìîóãîëüíèê íà çàäàííîå ïîëîæåíèå
*/
function addPoint(Point $point)
{
$result = clone $this;
$result->left += $point->left;
$result->top += $point->top;
return $result;
}
/**
* Êîîðäèíàòû òî÷êè ïðè âûðàâíèâàíèè ïðÿìîóãîëüíèêà îòíîñèòåëüíî òåêóùåãî
*/
function alignment(Rectangle $base)
{
return new Point((($base->left + $base->right) - ($this->left + $this->right)) / 2, $base->bottom - $this->height);
}
}
?>

136
core/httprequest.php Normal file
View file

@ -0,0 +1,136 @@
<?php
require_once 'core/safecollection.php';
require_once 'core/json.php';
require_once 'core/session.php';
/**
* Íåâåðíûé çàïðîñ
*/
class WrongRequestException extends Exception
{
}
// HTTPRequest = ArrayAccess
class HttpRequest extends Collection implements ArrayAccess
{
/**
* Constructor
* Stores "request data" in GPC order.
*/
public function __construct()
{
$list = array (
'data' => $_REQUEST,
'get' => $_GET,
'post' => $_POST,
'cookie' => $_COOKIE);
$ajax = $this->isAjax();
foreach ($list as $key => $value) {
$data = new SafeCollection();
if ($ajax) {
$data->import(json::prepare($value, array('self', 'unicode_decode')));
} else {
$data->import($value);
}
parent::set($key, $data);
}
$data = new Collection();
$data->import($GLOBALS['_FILES']);
parent::set('files', $data);
}
function get($key, $default = null)
{
return parent::get('data')->get($key, $default);
}
function session($value = false)
{
if ($value) {
$this->session = $value;
}
return $this->session;
}
function set($key, $value)
{
return parent::get('data')->set($key, $value);
}
function _get($key)
{
return parent::get($key);
}
function export()
{
return parent::get('data')->export();
}
/* Array Acces Interface */
function offsetExists($offset)
{
}
function offsetGet($offset)
{
}
function offsetSet($offset, $value)
{
}
function offsetUnset($offset)
{
}
function clear()
{
return parent::get('data')->clear();
}
/**
* Allow access to data stored in GET, POST and COOKIE super globals.
*
* @param string $var
* @param string $key
* @return mixed
*/
public function getRawData($var, $key)
{
$data = parent::get(strtolower($var));
if ($data) {
return $data->get($key);
}
return null;
}
public function setRawData($var, $key, $val)
{
$data = parent::get(strtolower($var));
if ($data) {
return $data->set($key, $val);
}
}
public function setAction($name)
{
$this->setRawData('get', 'action', $name);
}
public function getAction()
{
$result = $this->getRawData('get', 'action');
return ($result) ? $result : 'index';
}
public function isAjax()
{
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest');
}
}

97
core/json.php Normal file
View file

@ -0,0 +1,97 @@
<?php
/**
* http://phptunes.blogspot.com/2007/01/phpjson.html
*/
class json
{
static $DEFAULT_ENCODING = 'windows-1251//IGNORE';
static $INTERNAL_ENCODING = 'utf-8';
static function encode($var)
{
return php2js($var); //json_encode(self::prepare($var, array('self', 'unicode_encode')));
}
// Ïðåîáðàçîâàíèå json â ìàññèâ
static function decode($var, $encoding = 'utf-8', $is_array = false)
{
if ($encoding != 'utf-8') $var = iconv($encoding, self::$INTERNAL_ENCODING, $var);
return self::prepare(json_decode($var, $is_array), array('self', 'unicode_decode'));
}
static function ident($var)
{
return $var;
}
/* windows-1251 -> utf-8 */
static function unicode_encode($var)
{
return @iconv(self::$DEFAULT_ENCODING, self::$INTERNAL_ENCODING, $var);
}
/* utf-8 -> windows-1251 */
static function unicode_decode($var)
{
return @iconv(self::$INTERNAL_ENCODING, self::$DEFAULT_ENCODING, $var);
}
static function prepare($var, $encode)
{
if (is_array($var)) {
$new = array();
foreach ($var as $k => $v) {
$new[self::prepare($k, $encode)] = self::prepare($v, $encode);
}
$var = $new;
} elseif (is_object($var)) {
// Áûëî ïðåîáðàçîâàíèå òèïà äëÿ îòîáðàæåíèÿ !!
$vars = get_object_vars($var);
foreach ($vars as $m => $v) {
$var->$m = self::prepare($var->$m, $encode);
}
} elseif (is_string($var)) {
$var = call_user_func($encode, $var);
}
return $var;
}
}
function php2js($a = false) {
if (is_null($a)) return 'null';
if ($a === false) return 'false';
if ($a === true) return 'true';
if (is_scalar($a)) {
if (is_float($a)) {
// Always use "." for floats.
$a = str_replace(",", ".", strval($a));
} else if (is_int($a)) {
return $a;
}
// All scalars are converted to strings to avoid indeterminism.
// PHP's "1" and 1 are equal for all PHP operators, but
// JS's "1" and 1 are not. So if we pass "1" or 1 from the PHP backend,
// we should get the same result in the JS frontend (string).
// Character replacements for JSON.
static $jsonReplaces = array(
array("\\", "/", "\n", "\t", "\r", "\b", "\f", '"'),
array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
return '"' . str_replace($jsonReplaces[0], $jsonReplaces[1], $a) . '"';
}
$isList = true;
for ($i = 0, reset($a);$i < count($a);$i++, next($a)) {
if (key($a) !== $i) {
$isList = false;
break;
}
}
$result = array();
if ($isList) {
foreach($a as $v) $result[] = php2js($v);
return '[' . join(',', $result) . ']';
} else {
foreach($a as $k => $v) $result[] = php2js($k) . ':' . php2js($v);
return '{' . join(',', $result) . '}';
}
}

93
core/layout/layout.php Normal file
View file

@ -0,0 +1,93 @@
<?php
require_once 'core/functions.php';
// Ïåðåìåñòèòü â ôèëüòðû!!
/**
* Âûáîð ìàêåòà ñòðàíèöû.
* Âûáîð îôîðìëåíèÿ ñòðàíèöû îñóùåñòâëÿåòñÿ åñëè áûëî ñîâïàäåíèå ñ êàêèì ëèáî óñëîâèåì
*/
class LayoutManager extends Filter
{
// Ìàññèâ óñëîâèé ñ èõ ìàêåòàìè
protected $condition = array();
/**
* Ôóíêöèÿ êîòîðàÿ äîáàâëÿåò óñëîâèå äëÿ ïðîâåðêè ïàðàìåòðîâ $_GET
* @param $get array() | true Àññîöèàòèâíûé ìàññèâ êëþ÷åé è çíà÷åíèé äëÿ $_GET
*
* @example
* addConditionGet(array('module' => 'personal'), 'personal')
* addConditionGet(array('module' => 'login'), 'login')
*/
public function addConditionGet($get, Filter $layout)
{
$this->addCondition(rcurry(array($this, 'checkGet'), $get), $layout);
}
/**
* Óñëîâèå äëÿ àÿêñ çàïðîñîâ. Òîæå ñàìîå ÷òî è addConditionGet íî åùå ïðîâåðÿåòñÿ ÿâëÿåòñÿ ëè çàïðîñ ajax
*/
public function addConditionXHR($get, Filter $layout)
{
$this->addCondition(rcurry(array($this, 'checkXHR'), $get), $layout);
}
public function checkGet($request, $get)
{
if (is_array($get)) {
foreach ($get as $key => $value) {
if ($request->get($key) != $value) {
return false;
}
}
}
return true;
}
public function checkXHR($request, $get)
{
return $request->isAjax() && $this->checkGet($request, $get);
}
/**
* Äîáàâëÿåò åñëîâèå â îáùåì âèäå
* @parma $get function(HttpRequest) Ôóíêöèÿ
* @parma $layout Layout Ìàêåò
*/
public function addCondition($get, Filter $layout)
{
$this->condition [] = array($get, $layout);
}
/**
* Âûáèðàåò è ïðèìåíÿåò ìàêåò äëÿ ñòðàíèöû
*/
public function execute(Collection $request)
{
foreach ($this->condition as $condition) {
if (call_user_func($condition[0], $request)) {
$layout = $condition[1];
$view = $layout->execute($request);
if ($view instanceof View_Composite) {
echo $view->render();
} else {
echo $view;
}
return null;
}
}
}
}
/**
* Ñàìûé ïðîñòîé ìàêåò
*/
class LayoutNone extends Filter
{
function execute(Collection $request)
{
return $this->processor->execute($request);
}
}

210
core/mail.php Normal file
View file

@ -0,0 +1,210 @@
<?php
/**
* Êëàññ äëÿ ðàáîòû ñ ïî÷òîé
* http://en.wikipedia.org/wiki/MIME
*/
class Mail
{
public $from;
public $to;
public $subject;
public $content;
public $copy;
private $encoding;
private $notify= false;
protected $attachment = array ();
protected $uniqid;
function __construct() {
$this->setEncoding("windows-1251");
$this->uniqid = strtoupper(uniqid(time())); // Èäåíòåôèêàòîð ðàçäåëèòåëÿ
// $this->mime
}
/**
* Óñòàíîâêà îòïðàâèòåëÿ
*/
function from($name)
{
$this->from = $name;
}
/**
* Óñòàíîâêà ïîëó÷àòåëÿ
*/
function to($name) // recipient
{
$this->to = $name;
}
/**
* Óñòàíîâêà ïîëó÷àòåëåé êîïèè
*/
function copy($name) // recipient cc
{
$this->copy = $name;
}
function notify($notify)
{
$this->notify = $notify;
}
/**
* Òåìà ïèñüìà
*/
function subject($subject)
{
$this->subject = $subject;
}
/**
* Òåêñò ïèñüìà
*/
function setContent($text)
{
$this->content = $text;
}
/**
* Êîäèðîâêà òåêñòà â ïèñüìå
*/
function setEncoding($encoding)
{
$this->encoding = $encoding;
}
/**
* Äîáàâëåíèå âëîæåíèÿ èç ôàéëà
*/
function addAttachment($filename, $name = false)
{
assert(is_string($filename));
if(file_exists($filename)) { // assert ??
$file = fopen($filename, "rb");
$data = fread($file, filesize($filename));
$this->attachment [] = ($name) ? array($data, $name) : array($data, basename($filename));
}
}
/**
* Äîáàâëåíèå âëîæåíèÿ èç ñòðîêè ñ óêàçàíèåì èìåíè ôàéëà
*/
function addAttachmentRaw($data, $name)
{
assert(is_string($name));
$this->attachment [] = array($data, $name);
}
function quote($var, $val)
{
return ";" . PHP_EOL . "\t" . $var . "=\"" . $val . "\"";
}
/**
* Îáùèé ôîðìàò òåãîâ MIME
* http://tools.ietf.org/html/rfc2045
*/
function mimeTag($name, $value, array $args = array())
{
assert (is_string($name));
assert (is_string($value));
return $name . ": " . $value . implode("", array_map(array($this, 'quote'), array_keys($args), array_values($args))) . PHP_EOL;
}
/**
*
* http://tools.ietf.org/html/rfc2047
*/
function encodedWord($text, $encoding = 'B')
{
return "=?{$this->encoding}?$encoding?".base64_encode($text)."?=";
}
/**
* Òåëî ñîîáùåíèÿ
*/
function getMessage()
{
$message = "--".$this->uniqid . PHP_EOL;
$message .= $this->mimeTag("Content-Type", "text/plain", array ('charset' => $this->encoding));
$message .= $this->mimeTag("Content-Transfer-Encoding", "8bit");
$message .= PHP_EOL . $this->content . PHP_EOL . PHP_EOL;
/**
* Âëîæåíèÿ
* http://tools.ietf.org/html/rfc2046#section-5.1.3
*/
foreach ($this->attachment as $value) {
list($data, $name) = $value;
$message .= "--" . $this->uniqid . PHP_EOL;
$message .= $this->mimeTag("Content-Type", "application/octet-stream", array ('name' => $name));
$message .= $this->mimeTag("Content-Transfer-Encoding", "base64");
$message .= $this->mimeTag("Content-Disposition", "attachment", array ('filename' => $name));
$message .= PHP_EOL . chunk_split(base64_encode($data)) . PHP_EOL;
}
return $message;
}
/**
* Çàãîëîâîê ñîîáùåíèÿ
*/
function getHeader()
{
$head = $this->mimeTag("MIME-Version", "1.0");
$head .= $this->mimeTag("From", $this->from);
$head .= $this->mimeTag("X-Mailer", "CIS Tool");
$head .= $this->mimeTag("Reply-To", $this->from);
if ($this->notify) {
$head .= $this->mimeTag("Disposition-Notification-To", "\"" . $this->notify . "\" <" . $this->from . ">");
}
$head .= $this->mimeTag("Content-Type", "multipart/mixed", array ("boundary" => $this->uniqid));
if ($this->copy) {
$head .= $this->mimeTag("BCC", $this->copy);
}
$head .= PHP_EOL;
return $head;
}
function getSubject()
{
return $this->encodedWord($this->subject);
}
/**
* Âûâîä ñòðîêè äëÿ ñîõðàíåíèÿ â ôîðìàòå .eml
*/
function eml()
{
return "To: " . $this->to . PHP_EOL . "Subject: {$this->getSubject()}" . PHP_EOL . $this->getHeader() . $this->getMessage();
}
/**
* Îòïðàâêà ïî÷òû
*/
function send()
{
$result = mail($this->to, $this->getSubject(), $this->getMessage(), $this->getHeader());
// $result = false;
if(! $result) {
require_once "core/path.php";
file_put_contents(Path::resolveFile("data/email/send.eml"), $this->eml());
}
return $result;
}
function clear() {
foreach ($this->attachment as $key => &$value) {
unset($this->attachment[$key]);
}
$this->attachment = array();
}
}

30
core/mapper/factory.php Normal file
View file

@ -0,0 +1,30 @@
<?php
class ModelFactory
{
static $shortcut = "model";
public function __construct (Connection $db)
{
$this->db = $db;
}
/**
* Ñîçäàåò ìîäåëü
* @param string $name
* @return model
*/
public function getModel ($name)
{
require_once 'core/mapper/mapper.php'; // ????
require_once (Shortcut::getUrl(self::$shortcut, $name));
$modelName = $name . "Mapper";
$model = new $modelName();
$model->db = $this->db;
$model->factory = $this;
return $model;
}
}
?>

267
core/mapper/mapper.php Normal file
View file

@ -0,0 +1,267 @@
<?php
require_once 'core/primitive.php';
/**
* Èñïîëüçîâàòü èíòåðôåéñû ÷òîáû îïðåäåëèòü êàêèå äåéñòâèÿ ìîæíî ñîâåðøàòü ñ îáüåêòîì è òàêèì îáðàçîì
* Ñòðîèòü íàáîð äåéñòâèé Action è îòîáðàæåíèé View äëÿ îáüåêòà
* Ò.ê îòîáðàæåíèå äàííûõ ìîæåò áûòü íå òîëüêî íà òàáëèöó áàç äàííûõ
* È âîçìîæíî ðåàëèçîâàííû âñå èíòåðôåéñû
*/
interface IDataList
{
function findAll (Collection $request, $id = null);
function findById ($id);
function getCount (Collection $request, $id);
}
interface IDataSave
{
function saveTo ($o);
function updateTo ($o);
}
/**
* Îòîáðàæåíèå òàáëèöû áàçû äàííûõ â îáüåêòû
* Mapper -> DataMapper implements IDataList, IDataSave, IDataSort, IDataDelete ...
*
* @package core
*/
class DataMapper implements IDataList
{
/* Õðàíèòü ìåòàäàííûå â ñòàòè÷åñêîì ñâîéñòâå êëàññà äëÿ îòîòáðàæåíèÿ ?!, + Ñêðèïò äëÿ ãåíåðàöèè ìåòàäàííûõ!!
*/
public $factory;
public $className; /* Êëàññ íà êîòîðûé áóäåò îòîáðàæàòüñÿ ñòðî÷êà òàáëèöû */
public $filter = ""; /* */
public $schema = array (); /* Ñîîòâåòñòâèå ìåæäó ñâîéñòâîì îáüåêòà è ñòîëáöîì, äîáàâèòü òèï äëÿ çàïèñåé !! */
public $database; /* Òàáëèöà */
public $index; /* Èíäåêñíûé ñòîëáåö */
public $db; /* Ñîåäèíåíèå ñ áàçîé äàííûõ */
public $reference = array (null, null);
public function __construct ()
{
}
public function setRange ($stmt, $page, $size)
{
$stmt->setLimit ($size);
$stmt->setOffset (($page-1) * $size);
}
public function listSQL (array $list)
{
return implode ($list, ",");
}
/**
* Ïîèñê ñòðîêè â òàáëèöå ïî èäåíòèôèêàòîðó
* @param $id Çíà÷åíèå èäåíòèôèêàòîðà
* @return Îáüåêò êëàññà $className
*/
public function findById ($id)
{
// Ñòðîêè çàïðîñà ïðåîáðàçîâàòü â ìåòîäû (getSQLSelect ...)
// Query::from($this->database)->where ($this->index, "=", $id)->select();
$stmt = $this->db->prepareStatement ("SELECT * FROM ".$this->database." WHERE ".$this->index." = ?");
$stmt->setInt (1, $id);
$rs = $stmt->executeQuery ();
$rs->next ();
return $this->mapOne ($rs);
}
/**
* Ïðåîáðàçóåò parseResult â îáüåêò
*/
public /* private */ function mapOne ($rs)
{
$result = new $this->className ();
foreach ($this->schema as $key => $value) {
list($value) = $value;
$result->$value->setRes($rs, $key);
}
return $result;
}
public /* private */ function mapAll ($rs)
{
$result = array ();
// Ïðåîáðàçîâàíèå SQL â îáüåêò
while ($rs->next ()) {
$result[] = $this->mapOne ($rs);
}
return $result;
}
private function clean ($value) {
return strtolower(trim(iconv('utf-8', 'cp1251', $value)));
}
/**
* Ïðåîáðàçóåò ïàðàìåòðû ôîðìû â SQL çàïðîñ WHERE
* @param array $params
* @param array $schema
* @return string
*/
public function requestToSQL (Collection $request, array $schema)
{
$result = array ();
foreach ($schema as $key => $value) {
$param = $request->get ($key);
if ($param) {
array_push ($result, "lower (".$value.") LIKE '".$this->clean ($param)."%'");
}
}
if (empty ($result)) return null;
return implode ($result, " AND ");
}
/**
* Óäàëåíèå ñòðîê èç òàáëèöû ñ çàäàííûìè èíäåêñàìè
* @param $list array Ìàññèâ èäåíòåôèêàòîðîâ
*/
public function deleteList (array $list)
{
// Query::from($this->database)->where($this->index, "in", $list)->delete();
$sql = "DELETE FROM " . $this->database . " WHERE " . $this->index . " IN (" . $this->listSQL ($list) . ")";
return $this->db->executeQuery ($sql);
}
public static function findKey (array $schema, $sort)
{
foreach ($schema as $key => $item) {
list($item) = $item;
if ($item == $sort) {
return $key;
}
}
return $sort;
}
public function getOrder (Collection $request)
{
$order = "";
$sort = $request->get('key');
$desc = ($request->get('desc') == 0)? 'DESC' : 'ASC';
if ($sort) {
$sort = self::findKey ($this->schema, $sort);
$order = " ORDER BY $sort $desc";
}
return $order;
}
/**
* Èçâëåêàåò ñïèñîê çàïèñåé èç áàçû äàííûõ
*/
public function findAll (Collection $request, $id = null)
{
$name0 = $this->database;
$foreign = $this->reference[1];
// Ïåðåïèñàòü èñïîëüçóÿ Query !!!
if ($foreign && $id) {
$filter = ($this->filter)?$filter = " AND ".$this->filter: "";
$sql = "SELECT t1.* FROM $name0 as t1 WHERE t1.$foreign = $id " . $filter.self::getOrder($request);
} else {
$filter = ($this->filter)?$filter = " WHERE " . $this->filter: "";
$sql = "SELECT * FROM $name0 " . $filter . self::getOrder($request);
}
$stmt = $this->db->prepareStatement ($sql);
$page = $request->get('page');
$limit = $request->get('size');
if ($page && $limit) {
$this->setRange($stmt, $page, $limit);
}
return $this->mapAll($stmt->executeQuery());
}
public function getCount (Collection $request, $id)
{
$name0 = $this->database;
$foreign = $this->reference[1];
// Ïåðåïèñàòü èñïîëüçóÿ Query !!!
if ($foreign && $id) {
$filter = ($this->filter)?$filter = " AND " . $this->filter: "";
$sql = "SELECT count(t1.*) as length FROM $name0 as t1 WHERE t1.$foreign = $id " . $filter;
} else {
$filter = ($this->filter)?$filter = " WHERE " . $this->filter: "";
$sql = "SELECT count(*) as length FROM $name0 " . $filter;
}
$rs = $this->db->executeQuery($sql);
$rs->next();
return $rs->getInt('length');
}
/**
* Äîáàâëåíèå çàïèñè â áàçó äàííûõ
* @param $o Îáüåêò äëÿ çàïèñè â áàçó äàííûõ
*/
public function saveTo (Model $o)
{
$keys = array ();
$values = array ();
foreach ($this->schema as $key => $value) {
list($value) = $value;
if ($key != $this->index) {
$keys[] = $key;
$values[] = "'".$o->$value."'";
}
}
$stmt = $this->db->prepareStatement ("INSERT INTO ".$this->database." (".implode ($keys, ",").") VALUES (".implode ($values, ",").")");
$stmt->executeQuery ();
}
/**
* Îáíîâëÿåò çàïèñü â áàçå äàííûõ
* @param $o Îáüåêò äëÿ îáíîâëåíèÿ
*/
public function updateTo (Model $o)
{
$keys_values = array ();
foreach ($this->schema as $key => $value) {
list($value) = $value;
if ($key != $this->index && !($o->$value instanceof FKey)) {
$keys_values[] = $key." = '".$o->$value."'";
}
}
// Äëÿ âñåõ äîëæåí áûòü èäåíòåôèêàòîð id
$stmt = $this->db->prepareStatement ("UPDATE ".$this->database." SET ".implode($keys_values, ",")." WHERE ".$this->index." = ".$o->id);
$stmt->executeQuery ();
}
function saveDB (Model $o)
{
if ($o->id) {
$this->updateTo($o);
} else {
$this->saveTo($o);
}
}
function getModel($name)
{
require_once 'core/Mapper/Factory.php';
if (!$this->factory) {
$this->factory = new ModelFactory($this->db);
}
return $this->factory->getModel($name);
}
}
/**
*
*/
class Model
{
public function __construct ()
{
foreach (get_class_vars (get_class ($this)) as $key => $value) {
$this->$key = new Primitive ();
}
}
// __get, __set ìåòîäû. Â ìåòàäàííûõ õðàíèòñÿ òèï ñâîéñòâ, ïðîâåðÿòü ïðè ïðèñâàèâàíèè!!
}
?>

View file

@ -0,0 +1,78 @@
<?php
/**
* Îòîáðàæåíèå ñïèñêà ïàïîê ñ íàñòðîéêàìè íà îáüåêò
*/
class PathMapper
{
private $count;
private $base = null;
public $reference = null;
function plane (&$target, Collection $array)
{
$vars = get_class_vars(get_class($target));
foreach ($vars as $name => $value) {
$target->$name = $array->get($name);
}
}
function basePath ()
{
if ( ! $this->base) $this->base = $this->getBasePath();
return $this->base;
}
function findAll (Collection $request, $id = null)
{
require_once "core/settings.php";
require_once "core/path.php";
$this->reference = $id;
$base = $this->basePath ();
$path = new Path($base);
$list = $path->getContent();
$result = array ();
$this->count = 0;
foreach ($list as $name) {
if (is_dir (Path::join($this->basePath (), $name))
&& $module = $this->findById ($name)) {
$this->count++;
$result [] = $module;
}
}
return $result;
}
function findById ($name)
{
$file = Path::join($this->basePath(), $this->getSettingsFile ($name));
if (file_exists($file)) {
$settings = new Settings($file);
$settings->read();
return $this->settingsMap($name, $settings);
}
return null;
}
/**
* ×èñëî ïàïîê
*/
function getCount ()
{
return $this->count;
}
/**
* Óäàëåíèå ñïèñêà ïàïîê
*/
function deleteList(array $list)
{
foreach ($list as $name)
Path::delete(Path::join($this->getBasePath(), $name));
}
}
?>

View file

@ -0,0 +1,113 @@
<?php
/**
Copyright (c) 2007 Brady Mulhollem
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**/
class Simple_BB_Code{
//General Tags
var $tags = array('b' => 'strong','i' => 'em','u' => 'span style="text-decoration:underline"','quote' => 'blockquote','s' => 'span style="text-decoration: line-through"', 'list' => 'ul','\*' => 'li');
//Tags that must be mapped to diffierent parts
var $mapped = array('url' => array('a','href',true),'img' => array('img','src',false));
//Tags with atributes
var $tags_with_att = array('color' => array('font','color'),'size' => array('font','size'),'url' => array('a','href'));
//Gotta have smilies
var $smilies = array(':)' => 'smile.gif',':(' => 'frown.gif');
//Config Variables
//Convert new line charactes to linebreaks?
var $convert_newlines = true;
//Parse For smilies?
var $parse_smilies = true;
//auto link urls(http and ftp), and email addresses?
var $auto_links = true;
//Internal Storage
var $_code = '';
function Simple_BB_Code($new=true,$parse=true,$links=true){
$this->convert_newlines = $new;
$this->parse_smilies = $parse;
$this->auto_links = $links;
}
function parse($code){
$this->_code = $code;
$this->_strip_html();
$this->_parse_tags();
$this->_parse_mapped();
$this->_parse_tags_with_att();
$this->_parse_smilies();
$this->_parse_links();
$this->_convert_nl();
return $this->_code;
}
function _strip_html(){
$this->_code = strip_tags($this->_code);
}
function _convert_nl(){
if($this->convert_newlines){
$this->_code = nl2br($this->_code);
}
}
function _parse_tags(){
foreach($this->tags as $old=>$new){
$ex = explode(' ',$new);
$this->_code = preg_replace('/\['.$old.'\](.+?)\[\/'.$old.'\]/is','<'.$new.'>$1</'.$ex[0].'>',$this->_code);
}
}
function _parse_mapped(){
foreach($this->mapped as $tag=>$data){
$reg = '/\['.$tag.'\](.+?)\[\/'.$tag.'\]/is';
if($data[2]){
$this->_code = preg_replace($reg,'<'.$data[0].' '.$data[1].'="$1">$1</'.$data[0].'>',$this->_code);
}
else{
$this->_code = preg_replace($reg,'<'.$data[0].' '.$data[1].'="$1">',$this->_code);
}
}
}
function _parse_tags_with_att(){
foreach($this->tags_with_att as $tag=>$data){
$this->_code = preg_replace('/\['.$tag.'=(.+?)\](.+?)\[\/'.$tag.'\]/is','<'.$data[0].' '.$data[1].'="$1">$2</'.$data[0].'>',$this->_code);
}
}
function _parse_smilies(){
if($this->parse_smilies){
foreach($this->smilies as $s=>$im){
$this->_code = str_replace($s,'<img src="'.$im.'">',$this->_code);
}
}
}
function _parse_links(){
if($this->auto_links){
$this->_code = preg_replace('/([^"])(http:\/\/|ftp:\/\/)([^\s,]*)/i','$1<a href="$2$3">$2$3</a>',$this->_code);
$this->_code = preg_replace('/([^"])([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})/i','$1<a href="mailto:$2">$2</a>',$this->_code);
}
}
function addTag($old,$new){
$this->tags[$old] = $new;
}
function addMapped($bb,$html,$att,$end=true){
$this->mapped[$bb] = array($html,$att,$end);
}
function addTagWithAttribute($bb,$html,$att){
$this->tags_with_att[$bb] = array($html,$att);
}
function addSmiley($code,$src){
$this->smilies[$code] = $src;
}
}
?>

24
core/numbers.php Normal file
View file

@ -0,0 +1,24 @@
<?php
class Numbers
{
static function roman($i)
{
return 0;
}
static function decimal($i)
{
return $i;
}
static function prefix($prefix, array $array)
{
$result = array();
for ($i = 0; $i < count($array); $i++) {
$result [] = call_user_func($prefix, $i + 1) . '. ' . $array[$i];
}
return $result;
}
}

319
core/path.php Normal file
View file

@ -0,0 +1,319 @@
<?php
/*.
require_module 'standard';
.*/
/**
* Êëàññ äëÿ ðàáîòû ñ ïàïêàìè è ïóòÿìè
* Äëÿ èòåðàöèè íàä ôàéëàìè âîçìîæíî ëó÷øå èñïîëüçîâàòü SPL
*
* @package utils
*/
class Path
{
const SEPARATOR = "/";
protected $path;
public function __construct ($path)
{
assert(is_string($path));
$this->path = $this->fromString($path);
$this->optimize();
}
static function factory($path) {
return new Path($path);
}
/**
* Âîçâðàùàåò ðàñøèðåíèå ôàéëà
*
* @param string $fileName Ïîëíîå èìÿ ôàéëà
*
* @return string
*/
static function getExtension ($fileName)
{
assert(is_string($fileName));
return pathinfo($fileName, PATHINFO_EXTENSION);
}
/**
* Ïîëíîå èìÿ ôàéëà áåç ðàñøèðåíèÿ
*
* @param string $fileName Èìÿ ôàéëà
*
* @return string
*/
static function skipExtension ($fileName)
{
assert(is_string($fileName));
$path = pathinfo($fileName);
if ($path['dirname'] == ".") {
return $path['filename'];
} else {
return self::join($path['dirname'], $path['filename']);
}
}
/**
* Âîçâðàùàåò èìÿ ôàéëà áåç ðàñøèðåíèÿ
*
* @param string $fileName Ïîëíîå èìÿ ôàéëà
*
* @return string
*/
static function getFileName ($fileName)
{
assert(is_string($fileName));
return pathinfo($fileName, PATHINFO_FILENAME);
}
/**
* Ñïèñîê ôàéëîâ â äèðåêòîðèè
*
* @param array $allow ìàññèâ ðàñøèðåíèé äëÿ ôàéëîâ
* @param array $ignore ìàññèâ èìåí ïààîê êîòîðûå íå íóæíî îáðàáàòûâàòü
*
* @return array
*/
public function getContent ($allow = null, $ignore = array())
{
$ignore = array_merge(array (".", "..", $ignore));
return self::fileList($this->__toString(), $allow, $ignore);
}
// Èñïîëüçîâàòü SPL ???
protected function fileList ($base, &$allow, &$ignore)
{
$result = array ();
if ($handle = opendir($base)) {
while (false !== ($file = readdir($handle))) {
if (! in_array ($file, $ignore)) {
$isDir = is_dir (Path::join ($base, $file));
if ($isDir || ($allow == null) || in_array (self::getExtension($file), $allow)) {
$result[] = $file;
}
}
}
closedir($handle);
}
return $result;
}
protected function fileListAll (&$result, $base, &$allow, &$ignore)
{
$files = self::fileList($base, $allow, $ignore);
foreach ($files as $name) {
$fullname = self::join($base, $name);
if (is_dir($fullname)) {
self::fileListAll($result, $fullname, $allow, $ignore);
} else {
array_push ($result, $fullname);
}
}
}
/**
* Ñïèñîê ôàéëîâ â äèðåêòîðèèè è åå ïîääèðåêòîðèé
*
* @param array $allow ìàññèâ ðàñøèðåíèé ðàçðåøåíûõ äëÿ ôàéëîâ
* @param array $ignore ìàññèâ èìåí ïààîê êîòîðûå íå íóæíî îáðàáàòûâàòü
*
* @return array
*/
function getContentRec ($allow = null, $ignore = array())
{
$result = array ();
$ignore = array_merge(array (".", ".."), $ignore);
self::fileListAll($result, $this->__toString(), $allow, $ignore);
return $result;
}
/**
* Ðåêóðñèâíî êîïèðóåò äèðåêòîðèþ
*
* @param string $source Ïàïêà èç êîòîðîé êîïèðóåòñÿ
* @param string $target Ïàïêà â êîòîðóþ êîïèðóåòñÿ
*/
public static function copy ($source, $target)
{
if (is_dir($source)) {
if (! file_exists($target)) mkdir ($target);
$path = new Path($source);
$files = $path->getContent();
foreach ($files as $file) {
$entry = self::join($source, $file);
if (is_dir($entry)) {
self::copy($entry, Path::join($target, $file));
} else {
copy($entry, Path::join($target, $file));
}
}
}
}
/**
* Ðåêóðñèâíî óäàëÿåò äèðåêòîðèþ
*
* @param string $path Ïàïêà
*/
public static function delete ($path)
{
assert(is_string($path));
if (is_dir($path)) {
foreach(glob($path . '/*') as $sf) {
if (is_dir($sf) && !is_link($sf)) {
self::delete($sf);
} else {
unlink($sf);
}
}
rmdir($path);
}
}
/**
* Ïðåîáðàçóåò ñòðîêó ïóòÿ â ìàññèâ
*
* @param string $path Ïóòü
*
* @return array
*/
public function fromString ($path)
{
assert(is_string($path));
$list = preg_split("/[\/\\\\]/", $path);
return $list;
}
/**
* Ïðåîáðàçóåò îòíîñèòåëüíûé ïóòü â àáñîëþòíûé
*/
public function optimize ()
{
$result = array(current($this->path));
while (next($this->path) !== false) {
$n = current ($this->path);
switch ($n) {
case "": break;
case ".": break;
case "..": if (count($result) > 0) array_pop($result); break;
default:
array_push($result, $n);
}
}
reset($this->path);
$this->path = $result;
}
/**
* Ïðåîáðàçóåò ïóòü â ñòðîêó
*
* @return string
*/
public function __toString ()
{
$result = implode($this->path, self::SEPARATOR);
return $result;
}
/**
* Ïðîâåðÿåò ÿâëÿåòñÿ ëè ïàïêà ðîäèòåëüñêîé äëÿ äðóãîé ïàïêè
*
* @parma Path $path
*
* @return boolean
*/
public function isParent ($path)
{
if (count($path->path) > count($this->path)) {
for ($i = 0; $i < count($this->path); $i++) {
if ($path->path[$i] != $this->path[$i]) {
return false;
}
}
return true;
}
return false;
}
/**
* Íàõîäèò ïóòü îòíîñèòåëüíî òåêóùåãî ïóòÿ
*
* @param string $name Ïîëíûé ïóòü ê ôàéëó
*
* @return string Îòíîñèòåëüíûé ïóòü ê ôàéëó
*/
public function relPath ($name)
{
$path = new Path ($name);
foreach ($this->path as $n) {
array_shift($path->path);
}
return $path->__toString();
}
public function append ($path)
{
$base = $this->__toString();
return self::join($base, $path);
}
/**
* Ñîçäàåò íåäàñòàþùèå ïàïêè äëÿ çàïèñè ôàéëà
*
* @param string $dst Ïîëíîå èìÿ ôàéëà
*
* @return void
*/
static function prepare ($dst)
{
$path_dst = pathinfo($dst, PATHINFO_DIRNAME);
if (! file_exists($path_dst)) {
mkdir($path_dst);
}
}
/**
* Ïîäáèðàåò íîâîå âðåìåííîå èìÿ äëÿ ôàéëà
*
* @param string $dst Ïðåäïîëîãàåìîå èìÿ ôàéëà
*
* @return string Íîâîå èìÿ ôàéëà
*/
static function resolveFile ($dst)
{
$i = 0;
$file = self::skipExtension($dst);
$suffix = self::getExtension($dst);
$temp = $dst;
while (file_exists($temp)) {
$i ++;
$temp = $file . "." . $i . "." . $suffix;
}
return $temp;
}
/**
* Îáüåäèíÿåò ñòðîêè â ïóòü ñîåäèíÿÿ íåîáõîäèìûì ðàçäåëèòåëåì
*
* @return string
*/
static function join ()
{
$args = func_get_args();
return implode(self::SEPARATOR, $args);
}
}
?>

105
core/primitive.php Normal file
View file

@ -0,0 +1,105 @@
<?php
/**
* Êëàññ ïðåîáðàçîâàíèÿ òèïà çíà÷åíèÿ ïîëÿ êëàññà â òèï ïîëÿ òàáëèöû
* @package core
*/
class Primitive
{
public $value;
public $name;
public function __construct ($name = "")
{
$this->name = $name;
}
// Ïðåîáðàçîâàíèå èç âíåøíåãî âîðìàòà
public function setString ($value)
{
$this->value = $value;
}
// Ïðåîáðàçîâàíèå èç ôîðìàòà áàçû äàííûõ
public function setRes ($res, $key)
{
$this->value = $res->getString ($key);
}
public function __toString ()
{
return ((string) $this->value);
}
// Ïðåîáðàçîâàíèå âî âíåøíèé ôîðìàò
public function getString ()
{
return $this->__toString ();
}
}
/**
* Îòîáðàæåíèå ïîëÿ òàáëèöû â öåëîå ÷èñëî
* @package core
*/
class Int4 extends Primitive {
public function setRes ($res, $key) {
$this->value = $res->getInt ($key);
}
public function setString ($value) {
$this->value = ((int) $value);
}
}
/* Foreign key */
class FKey extends Int4 {}
/**
* Îòîáðàæåíèå ïîëÿ òàáëèöû â äàòó - âðåìÿ
*/
class Date extends Primitive
{
public function setRes ($res, $key)
{
$this->value = $res->getInt ($key);
}
public function setString ($value)
{
$this->value = 0;
if ($tmp = explode("/",$value,3)) {
if ($tmp[1] && $tmp[0] && $tmp[2]) {
if (checkdate($tmp[1], $tmp[0], $tmp[2])) {
$this->value = mktime(0, 0, 0, $tmp[1], $tmp[0], $tmp[2]);
}
}
}
}
public function getString ()
{
return date ("d/m/Y", $this->value);
}
}
/**
*
*/
class Password extends Primitive
{
public function setRes ($res, $key)
{
$this->value = $res->getString($key);
}
public function setString ($value)
{
$this->value = md5($value);
}
public function getString ()
{
return $this->value;
}
}
?>

10
core/query/meta.php Normal file
View file

@ -0,0 +1,10 @@
<?php
/**
* Êëàññ ìåòàäàííûõ òàáëèöû
*/
class Meta
{
}
?>

206
core/query/query.php Normal file
View file

@ -0,0 +1,206 @@
<?php
require_once 'table.php';
require_once 'meta.php';
/**
* Êëàññ äëÿ ñîñòàâëåíèÿ çàïðîñà
*/
class Query
{
static $alias = 0;
public $table;
public $filter = array ();
public $calc = array ();
public $order = array ();
/**
* Ñîçäàåò ïóñòîé çàðîñ
*/
static function create()
{
return new Query();
}
/**
* Ìåòàäàííûå òàáëèöû
* @param string $name Èìÿ òàáëèöû
*/
function getTableMeta($name)
{
}
/**
* Ñîçäàåò íîâûé çàïðîñ
* @param string $name Èìÿ òàáëèöû
*
* @return Query
*/
public function from($name)
{
$result = clone $this;
$table = new Table();
$table->type = 'simple';
$table->name = $name;
$table->alias = "t" . self::$alias++;
$result->table = $table;
return $result;
}
/**
* Äîáàâëÿåò ê çàïðîñó óñëîâèå
* @param string $field Èìÿ ïîëÿ òàáëèöû
* @param string $op Èìÿ îïåðàòîðà
* @param $value Çíà÷åíèå ïîëÿ
*
* @return Query
*/
public function filter($field, $op, $value)
{
$result = clone $this;
$result->filter [] = $result->table->alias ."." . $field . $op . "'" . $value . "'";
return $result;
}
/**
* @param string $e Âûðàæåíèå
*/
public function calc($e)
{
$result = clone $this;
$result->calc [] = $e;
return $result;
}
public function joinOn($first, $e)
{
$result = $this->compose($first, array ('filter', 'calc', 'order'));
$e = strtr($e, array ("a." => $this->table->alias . ".",
"b." => $first->table->alias . "."));
$table = new Table ();
$table->type = 'join';
$table->name = $this->table->name;
$table->alias = $this->table->alias;
$table->join = $first->table;
$table->condition = $e;
$result->table = $table;
return $result;
}
/**
* Îáüåäèíÿåò ïàðàìåòðû äâóõ çàðîñîâ
* @param Query $first
* @pram array $list Ñïèñîê ïàðàìåòðîâ
*
* @return Query
*/
private function compose(Query $first, array $list)
{
$result = new Query();
foreach ($list as $name) {
$result->$name = array_merge($this->$name, $first->$name);
}
return $result;
}
/**
* Çàêîâû÷èâàåò çíà÷åíèå
*/
public function quote ($value)
{
return "'" . $value . "'";
}
/**
* Êîìïèëÿöèÿ òàáëèöû
* @param Table $table
*
* @return string ×àñòü ñòðîêè SQL
*/
private function table(Table $table)
{
if ($table->type == 'simple') {
return $table->name ." AS ".$table->alias;
}
if ($table->type == 'join') {
return $table->name ." AS ".$table->alias. " JOIN " . $this->table ($table->join) . " ON " . $table->condition;
}
return "";
}
/**
* Êîìïèëÿöèÿ WHERE
*
* @return string ×àñòü ñòðîêè SQL
*/
private function where ()
{
return implode(" AND ", $this->filter);
}
/**
* Êîìïèëÿöèÿ çàïðîñà â SELECT SQL
*
* @return string SQL âûðàæåíèå
*/
public function select()
{
return "SELECT "
. ((!empty($this->calc))? implode (",", $this->calc): "*")
. " FROM " . $this->table($this->table)
. ((!empty ($this->filter))? " WHERE " . $this->where() : "");
}
/**
* Êîìïèëÿöèÿ â DELETE
*/
public function delete()
{
return "DELETE FROM " . $this->table->name
. ((!empty ($this->filter))? " WHERE " . $this->where() : "");
}
private function add_prefix($prefix, $array) {
$result = array();
foreach ($array as $value) {
$result [] = $prefix . $value;
}
return $result;
}
/**
* Êîìïèëÿöèÿ â UPDATE
* TODO: Ðàçíûå òèïû çàïðîñîâ Query->update(); Query->select(), Query->insert();!!
* Âîçâðààùàþò statement
*/
public function update($values)
{
$pairs = array ();
foreach ($values as $key => $value) { //
$pairs [] = $key . "=" . $this->quote ($value);
}
return "UPDATE " . $this->table->name . " SET "
. implode(",", $pairs)
. ((!empty($this->filter))? " WHERE " . $this->where() : "");
}
/**
* Êîìïèëÿöèÿ â INSERT
*/
public function insert($values)
{
return "INSERT INTO ". $this->table->name . "("
. implode(",", array_keys($values))
. ") VALUES (" . implode(",", array_map(array($this, 'quote'), array_values($values))) . ")";
}
}
?>

865
core/query/sql.txt Normal file
View file

@ -0,0 +1,865 @@
// Version: 0.8
// ANTLR Version: 2.7.2
// Date: 2003.08.25
//
// Description: This is a MS SQL Server 2000 SELECT statement grammar.
//
// =======================================================================================
// Author: Tomasz Jastrzebski
// Contact: tdjastrzebski@yahoo.com
// Working parser/lexer generated based on this grammar will available for some time at:
// http://jastrzebski.europe.webmatrixhosting.net/mssqlparser.aspx
options {
language = "CSharp";
}
// PARSER ********************************************************************************
class SqlParser extends Parser;
options {
k = 2;
}
// starting rule
statement
: selectStatement (SEMICOLON)? EOF
;
selectStatement
:
queryExpression
(computeClause)?
(forClause)?
(optionClause)?
;
queryExpression
: subQueryExpression (unionOperator subQueryExpression)* (orderByClause)?
;
subQueryExpression
:
querySpecification
| LPAREN queryExpression RPAREN
;
querySpecification
:
selectClause
(fromClause)?
(whereClause)?
(groupByClause (havingClause)? )?
;
selectClause
: SELECT (ALL | DISTINCT)? (TOP Integer (PERCENT)? (WITH TIES)? )? selectList
;
whereClause
: WHERE searchCondition
;
orderByClause
: ORDER BY expression (ASC | DESC)? (COMMA expression (ASC | DESC)? )*
;
groupByClause
: GROUP BY (ALL)? expression (COMMA expression)* (WITH (CUBE | ROLLUP) )?
;
havingClause
: HAVING searchCondition
;
optionClause
: OPTION LPAREN queryHint (COMMA queryHint)* RPAREN
;
queryHint
:
(HASH | ORDER) GROUP
| (CONCAT | HASH | MERGE) UNION
| (LOOP | MERGE | HASH) JOIN
| FAST Integer
| FORCE ORDER
| MAXDOP Integer
| ROBUST PLAN
| KEEP PLAN
| KEEPFIXED PLAN
| EXPAND VIEWS
;
forClause
:
FOR (
BROWSE
| XML (RAW | AUTO | EXPLICIT) (COMMA XMLDATA)? (COMMA ELEMENTS)? (COMMA BINARY BASE64)
)
;
computeClause
:
COMPUTE
// only allowed functions are: AVG, COUNT, MAX, MIN, STDEV, STDEVP, VAR, VARP, SUM
identifier LPAREN expression RPAREN
(COMMA identifier LPAREN expression RPAREN)*
(BY expression (COMMA expression)* )?
;
searchCondition
: subSearchCondition ( (AND | OR) subSearchCondition )*
;
subSearchCondition
:
(NOT)? (
(LPAREN searchCondition RPAREN) => LPAREN searchCondition RPAREN
| predicate
)
;
predicate
:
(
expression (
// expression comparisonOperator expression
comparisonOperator (
expression
| (ALL | SOME | ANY) LPAREN selectStatement RPAREN
)
| IS (NOT)? NULL
| (NOT)? (
LIKE expression (ESCAPE expression)? // only single char
| BETWEEN expression AND expression
| IN LPAREN (
(selectStatement) => selectStatement
| expression (COMMA expression)*
) RPAREN
)
| CONTAINS LPAREN (dbObject | STAR) COMMA (stringLiteral | Variable) RPAREN
| FREETEXT LPAREN (dbObject | STAR) COMMA (stringLiteral | Variable) RPAREN
)
| EXISTS LPAREN selectStatement RPAREN
)
;
selectList
: selectItem ( COMMA selectItem )*
;
selectItem
:
STAR // "*, *" is a valid select list
| (
// starts with: "alias = column_name"
(alias2) => (
(alias2 dbObject COMMA) => alias2 column
| (alias2 dbObject (binaryOperator | LPAREN)) => alias2 expression
| (alias2 column) => alias2 column
| (alias2 expression) => alias2 expression
)
// all table columns: "table.*"
| (tableColumns) => tableColumns
// some shortcuts:
| (dbObject (alias1)? COMMA) => column (alias1)?
| (dbObject (binaryOperator | LPAREN) ) => expression (alias1)?
// less obvious cases:
| (column) => column (alias1)?
| (expression) => expression (alias1)?
)
;
fromClause
: FROM tableSource (COMMA tableSource)*
;
tableSource
: subTableSource (joinedTable)*
;
subTableSource
:
(
LPAREN (
(joinedTables) => joinedTables RPAREN
| (queryExpression) => queryExpression RPAREN alias1 // "derived table", mandatory alias
)
| (function) => function (alias1)?
| dbObject (alias1)? ( (WITH)? LPAREN tableHint (COMMA tableHint)* RPAREN )?
| Variable (alias1)?
| (CONTAINSTABLE | FREETEXTTABLE) LPAREN
dbObject COMMA (dbObject | STAR) COMMA (stringLiteral | Variable) (COMMA Integer)?
RPAREN (alias1)?
| COLON COLON function (alias1)? // built-in function
)
;
joinedTable
:
CROSS JOIN subTableSource
// "joinHint JOIN" is invalid join expression
| ( (INNER | (LEFT | RIGHT | FULL) (OUTER)? ) (joinHint)? )? JOIN tableSource ON searchCondition
;
joinedTables
: subTableSource (joinedTable)+
;
joinHint
:
LOOP
| HASH
| MERGE
| REMOTE
;
tableHint
:
INDEX (
LPAREN (identifier | Integer) ( COMMA (identifier | Integer) )* RPAREN
| ASSIGNEQUAL identifier // old index hint syntax
)
| FASTFIRSTROW
| HOLDLOCK
| NOLOCK
| PAGLOCK
| READCOMMITED
| READPAST
| READUNCOMMITED
| REPEATABLEREAD
| ROWLOCK
| SERIALIZABLE
| TABLOCK
| TABLOCKX
| UPDLOCK
| XLOCK
;
collate
: COLLATE identifier
;
alias1
: // alias name can also be single-quoted literal (but not for table names)
(AS)? (
identifier
| stringLiteral
| keywordAsIdentifier
)
;
alias2
:
(
identifier
| stringLiteral
| keywordAsIdentifier
)
ASSIGNEQUAL
;
tableColumns
:
o:dbObject DOT_STAR
;
column
:
(PLUS)* // "++column_name" is valid and updatable column name
(
dbObject
// for expression like "(column)" SQL Server returns updatable column
| LPAREN column RPAREN
)
(collate)? // it is not well documented but COLLATE can be used almost anywhere ...
;
expression
: // current definition ignores operator precedence
subExpression (binaryOperator subExpression)*
;
subExpression
:
(unaryOperator)?
(
constant
| Variable
| (function) => function
| LPAREN (
(selectStatement) => selectStatement // select statement returning a single value
| expression
) RPAREN
| dbObject // column
| parameterlessFunction
| caseFunction
| castFunction
)
(collate)? // it is not well documented but COLLATE can be used almost everywhere ...
;
// todo: create a separate rule for aggregate functions
function
: // LEFT and RIGHT keywords are also function names
(dbObject | LEFT | RIGHT) LPAREN (
expression (COMMA expression)*
| STAR // aggregate functions like Count(), Checksum() accept "*" as a parameter
| (ALL | DISTINCT) (STAR | expression) // aggregate function
| Variable ASSIGNEQUAL expression (COMMA Variable ASSIGNEQUAL expression)*
)?
RPAREN
;
caseFunction
: CASE (
expression (WHEN expression THEN expression)+
| (WHEN searchCondition THEN expression)+ // boolean expression
)
(ELSE expression)? END
;
castFunction
: CAST LPAREN expression AS identifier (LPAREN Integer (COMMA Integer)? RPAREN)? RPAREN
;
dbObject
// server.catalog.schema.object
// server.catalog..object
:
(identifier | IDENTITYCOL | ROWGUIDCOL | keywordAsIdentifier) (
DOT (identifier | IDENTITYCOL | ROWGUIDCOL | keywordAsIdentifier)
| (DOT DOT) => DOT DOT (identifier | IDENTITYCOL | ROWGUIDCOL | keywordAsIdentifier)
)*
;
parameterlessFunction
: // any others ?
CURRENT_TIMESTAMP
| CURRENT_USER
| SESSION_USER
| SYSTEM_USER
;
systemVariable
:
F_CONNECTIONS
| F_CPU_BUSY
| F_CURSOR_ROWS
| F_DATEFIRST
| F_DBTS
| F_ERROR
| F_FETCH_STATUS
| F_IDENTITY
| F_IDLE
| F_IO_BUSY
| F_LANGID
| F_LANGUAGE
| F_LOCK_TIMEOUT
| F_MAX_CONNECTIONS
| F_MAX_PRECISION
| F_NESTLEVEL
| F_OPTIONS
| F_PACK_RECEIVED
| F_PACK_SENT
| F_PACKET_ERRORS
| F_PROCID
| F_REMSERVER
| F_ROWCOUNT
| F_SERVERNAME
| F_SERVICENAME
| F_SPID
| F_TEXTSIZE
| F_TIMETICKS
| F_TOTAL_ERRORS
| F_TOTAL_READ
| F_TOTAL_WRITE
| F_TRANCOUNT
| F_VERSION
;
keywordAsIdentifier
:
(
AUTO
| BASE64
| BINARY
| CAST
| CONCAT
| CUBE
| ELEMENTS
| EXPAND
| EXPLICIT
| FAST
| FASTFIRSTROW
| FORCE
| HASH
| KEEP
| KEEPFIXED
| LOOP
| MAXDOP
| MERGE
| NOLOCK
| PAGLOCK
| RAW
| READCOMMITED
| READPAST
| READUNCOMMITED
| REMOTE
| REPEATABLEREAD
| ROBUST
| ROLLUP
| ROWLOCK
| SERIALIZABLE
| TABLOCK
| TABLOCKX
| TIES
| UPDLOCK
| VIEWS
| XLOCK
| XML
| XMLDATA
)
;
stringLiteral
:
UnicodeStringLiteral
| ASCIIStringLiteral
;
identifier
:
NonQuotedIdentifier
| QuotedIdentifier
;
constant
: Integer | Real | NULL | stringLiteral | HexLiteral | Currency | ODBCDateTime | systemVariable
;
unaryOperator
: PLUS | MINUS | TILDE
;
binaryOperator
: arithmeticOperator | bitwiseOperator
;
arithmeticOperator
: PLUS | MINUS | STAR | DIVIDE | MOD
;
bitwiseOperator
: AMPERSAND | TILDE | BITWISEOR | BITWISEXOR
;
comparisonOperator
:
ASSIGNEQUAL | NOTEQUAL1 | NOTEQUAL2 | LESSTHANOREQUALTO1 | LESSTHANOREQUALTO2
| LESSTHAN | GREATERTHANOREQUALTO1 | GREATERTHANOREQUALTO2 | GREATERTHAN
;
logicalOperator
: ALL | AND | ANY | BETWEEN | EXISTS | IN | LIKE | NOT | OR | SOME
;
unionOperator
: UNION (ALL)?
;
// LEXER *********************************************************************************
class SqlLexer extends Lexer;
options {
testLiterals = false;
k = 2;
caseSensitive = false;
caseSensitiveLiterals = false;
charVocabulary='\u0000'..'\uFFFE';
}
tokens {
ADD = "add" ;
ALL = "all" ;
ALTER = "alter" ;
AND = "and" ;
ANY = "any" ;
AS = "as" ;
ASC = "asc" ;
AUTHORIZATION = "authorization" ;
AUTO = "auto" ;
BACKUP = "backup" ;
BASE64 = "base64" ;
BEGIN = "begin" ;
BETWEEN = "between" ;
BINARY = "binary" ;
BREAK = "break" ;
BROWSE = "browse" ;
BULK = "bulk" ;
BY = "by" ;
CASCADE = "cascade" ;
CASE = "case" ;
CAST = "cast" ;
CHECK = "check" ;
CHECKPOINT = "checkpoint" ;
CLOSE = "close" ;
CLUSTERED = "clustered" ;
// COALESCE = "coalesce" ;
COLLATE = "collate" ;
COLUMN = "column" ;
COMMIT = "commit" ;
COMPUTE = "compute" ;
CONCAT = "concat" ;
CONSTRAINT = "constraint" ;
CONTAINS = "contains" ;
CONTAINSTABLE = "containstable" ;
CONTINUE = "continue" ;
// CONVERT = "convert" ;
CREATE = "create" ;
CROSS = "cross" ;
CUBE = "cube" ;
CURRENT = "current" ;
CURRENT_DATE = "current_date" ;
CURRENT_TIME = "current_time" ;
CURRENT_TIMESTAMP = "current_timestamp" ;
CURRENT_USER = "current_user" ;
CURSOR = "cursor" ;
DATABASE = "database" ;
DBCC = "dbcc" ;
DEALLOCATE = "deallocate" ;
DECLARE = "declare" ;
DEFAULT = "default" ;
DELETE = "delete" ;
DENY = "deny" ;
DESC = "desc" ;
DISK = "disk" ;
DISTINCT = "distinct" ;
DISTRIBUTED = "distributed" ;
DOUBLE = "double" ;
DROP = "drop" ;
// DUMMY = "dummy" ;
DUMP = "dump" ;
ELEMENTS = "elements" ;
ELSE = "else" ;
END = "end" ;
ERRLVL = "errlvl" ;
ESCAPE = "escape" ;
EXCEPT = "except" ;
EXEC = "exec" ;
EXECUTE = "execute" ;
EXISTS = "exists" ;
EXIT = "exit" ;
EXPAND = "expand" ;
EXPLICIT = "explicit" ;
FAST = "fast" ;
FASTFIRSTROW = "fastfirstrow" ;
FETCH = "fetch" ;
FILE = "file" ;
FILLFACTOR = "fillfactor" ;
FOR = "for" ;
FORCE = "force" ;
FOREIGN = "foreign" ;
FREETEXT = "freetext" ;
FREETEXTTABLE = "freetexttable" ;
FROM = "from" ;
FULL = "full" ;
FUNCTION = "function" ;
GOTO = "goto" ;
GRANT = "grant" ;
GROUP = "group" ;
HASH = "hash" ;
HAVING = "having" ;
HOLDLOCK = "holdlock" ;
IDENTITY = "identity" ;
IDENTITY_INSERT = "identity_insert" ;
IDENTITYCOL = "identitycol" ;
IF = "if" ;
IN = "in" ;
INDEX = "index" ;
INNER = "inner" ;
INSERT = "insert" ;
INTERSECT = "intersect" ;
INTO = "into" ;
IS = "is" ;
JOIN = "join" ;
KEEP = "keep" ;
KEEPFIXED = "keepfixed" ;
KEY = "key" ;
KILL = "kill" ;
LEFT = "left" ;
LIKE = "like" ;
LINENO = "lineno" ;
LOAD = "load" ;
LOOP = "loop" ;
MAXDOP = "maxdop" ;
MERGE = "merge" ;
NATIONAL = "national" ;
NOCHECK = "nocheck" ;
NOLOCK = "nolock" ;
NONCLUSTERED = "nonclustered" ;
NOT = "not" ;
NULL = "null" ;
// NULLIF = "nullif" ;
OF = "of" ;
OFF = "off" ;
OFFSETS = "offsets" ;
ON = "on" ;
OPEN = "open" ;
OPENDATASOURCE = "opendatasource" ;
OPENQUERY = "openquery" ;
OPENROWSET = "openrowset" ;
OPENXML = "openxml" ;
OPTION = "option" ;
OR = "or" ;
ORDER = "order" ;
OUTER = "outer" ;
OVER = "over" ;
PAGLOCK = "paglock" ;
PERCENT = "percent" ;
PLAN = "plan" ;
PRECISION = "precision" ;
PRIMARY = "primary" ;
PRINT = "print" ;
PROC = "proc" ;
PROCEDURE = "procedure" ;
PUBLIC = "public" ;
RAISERROR = "raiserror" ;
RAW = "raw" ;
READ = "read" ;
READCOMMITED = "readcommited" ;
READPAST = "readpast" ;
READTEXT = "readtext" ;
READUNCOMMITED = "readuncommited" ;
RECONFIGURE = "reconfigure" ;
REFERENCES = "references" ;
REMOTE = "remote" ;
REPEATABLEREAD = "repeatableread" ;
REPLICATION = "replication" ;
RESTORE = "restore" ;
RESTRICT = "restrict" ;
RETURN = "return" ;
REVOKE = "revoke" ;
RIGHT = "right" ;
ROBUST = "robust" ;
ROLLBACK = "rollback" ;
ROLLUP = "rollup" ;
ROWCOUNT = "rowcount" ;
ROWGUIDCOL = "rowguidcol" ;
ROWLOCK = "rowlock" ;
RULE = "rule" ;
SAVE = "save" ;
SCHEMA = "schema" ;
SELECT = "select" ;
SERIALIZABLE = "serializable" ;
SESSION_USER = "session_user" ;
SET = "set" ;
SETUSER = "setuser" ;
SHUTDOWN = "shutdown" ;
SOME = "some" ;
STATISTICS = "statistics" ;
SYSTEM_USER = "system_user" ;
TABLE = "table" ;
TABLOCK = "tablock" ;
TABLOCKX = "tablockx" ;
TEXTSIZE = "textsize" ;
THEN = "then" ;
TIES = "ties" ;
TO = "to" ;
TOP = "top" ;
TRAN = "tran" ;
TRANSACTION = "transaction" ;
TRIGGER = "trigger" ;
TRUNCATE = "truncate" ;
TSEQUAL = "tsequal" ;
UNION = "union" ;
UNIQUE = "unique" ;
UPDATE = "update" ;
UPDATETEXT = "updatetext" ;
UPDLOCK = "updlock" ;
USE = "use" ;
USER = "user" ;
VALUES = "values" ;
VARYING = "varying" ;
VIEW = "view" ;
VIEWS = "views" ;
WAITFOR = "waitfor" ;
WHEN = "when" ;
WHERE = "where" ;
WHILE = "while" ;
WITH = "with" ;
WRITETEXT = "writetext" ;
XLOCK = "xlock" ;
XML = "xml" ;
XMLDATA = "xmldata" ;
// system variables
F_CONNECTIONS = "@@connections" ;
F_CPU_BUSY = "@@cpu_busy" ;
F_CURSOR_ROWS = "@@cursor_rows" ;
F_DATEFIRST = "@@datefirst" ;
F_DBTS = "@@dbts" ;
F_ERROR = "@@error" ;
F_FETCH_STATUS = "@@fetch_status" ;
F_IDENTITY = "@@identity" ;
F_IDLE = "@@idle" ;
F_IO_BUSY = "@@io_busy" ;
F_LANGID = "@@langid" ;
F_LANGUAGE = "@@language" ;
F_LOCK_TIMEOUT = "@@lock_timeout" ;
F_MAX_CONNECTIONS = "@@max_connections" ;
F_MAX_PRECISION = "@@max_precision" ;
F_NESTLEVEL = "@@nestlevel" ;
F_OPTIONS = "@@options" ;
F_PACK_RECEIVED = "@@pack_received" ;
F_PACK_SENT = "@@pack_sent" ;
F_PACKET_ERRORS = "@@packet_errors" ;
F_PROCID = "@@procid" ;
F_REMSERVER = "@@remserver" ;
F_ROWCOUNT = "@@rowcount" ;
F_SERVERNAME = "@@servername" ;
F_SERVICENAME = "@@servicename" ;
F_SPID = "@@spid" ;
F_TEXTSIZE = "@@textsize" ;
F_TIMETICKS = "@@timeticks" ;
F_TOTAL_ERRORS = "@@total_errors" ;
F_TOTAL_READ = "@@total_read" ;
F_TOTAL_WRITE = "@@total_write" ;
F_TRANCOUNT = "@@trancount" ;
F_VERSION = "@@version" ;
}
// Operators
protected DOT:; // generated as a part of Number rule
COLON : ':' ;
COMMA : ',' ;
SEMICOLON : ';' ;
LPAREN : '(' ;
RPAREN : ')' ;
//LSQUARE : '[' ;
//RSQUARE : ']' ;
ASSIGNEQUAL : '=' ;
NOTEQUAL1 : "<>" ;
NOTEQUAL2 : "!=" ;
LESSTHANOREQUALTO1 : "<=" ;
LESSTHANOREQUALTO2 : "!>" ;
LESSTHAN : "<" ;
GREATERTHANOREQUALTO1 : ">=" ;
GREATERTHANOREQUALTO2 : "!<" ;
GREATERTHAN : ">" ;
DIVIDE : '/' ;
PLUS : '+' ;
MINUS : '-' ;
STAR : '*' ;
MOD : '%' ;
AMPERSAND : '&' ;
TILDE : '~' ;
BITWISEOR : '|' ;
BITWISEXOR : '^' ;
DOT_STAR : ".*" ;
Whitespace
: (' ' | '\t' | '\n' | '\r')
{ _ttype = Token.SKIP; }
;
// COMMENTS
SingleLineComment
: "--"( ~('\r' | '\n') )*
{ _ttype = Token.SKIP; }
;
MultiLineComment
: "/*" (~'*')* '*' ('*' | ( ~('*' | '/') (~'*')* '*') )* '/'
{ _ttype = Token.SKIP; }
;
// LITERALS
protected
Letter
: 'a'..'z' | '_' | '#' | '@' | '\u0080'..'\ufffe'
;
protected
Digit
: '0'..'9'
;
protected
Integer :;
protected
Real :;
protected
Exponent
: 'e' ( '+' | '-' )? (Digit)+
;
Number
:
( (Digit)+ ('.' | 'e') ) => (Digit)+ ( '.' (Digit)* (Exponent)? | Exponent) { _ttype = Real; }
| '.' { _ttype = DOT; } ( (Digit)+ (Exponent)? { _ttype = Real; } )?
| (Digit)+ { _ttype = Integer; }
| "0x" ('a'..'f' | Digit)* { _ttype = HexLiteral; } // "0x" is valid hex literal
;
protected
Currency
: // generated as a part of NonQuotedIdentifier rule
('$' | '\u00a3'..'\u00a5' | '\u09f2'..'\u09f3' | '\u0e3f' | '\u20a0'..'\u20a4' | '\u20a6'..'\u20ab')
((Digit)+ ('.' (Digit)* )? | '.' (Digit)+)
;
ODBCDateTime
: '{' (Whitespace)? ("ts" | 't' | 'd') (Whitespace)?
('n')? '\'' (~'\'')* '\'' ( '\'' (~'\'')* '\'' )* (Whitespace)? '}'
;
NonQuotedIdentifier
options { testLiterals = true; }
:
(Currency) => Currency { _ttype = Currency; }
| ('a'..'z' | '_' | '#' | '\u0080'..'\ufffe') (Letter | Digit)* // first char other than '@'
;
QuotedIdentifier
:
(
'[' (~']')* ']' (']' (~']')* ']')*
| '"' (~'"')* '"' ('"' (~'"')* '"')*
)
;
Variable
// test for literals in case of a function begining with '@' (eg. "@@ERROR")
options { testLiterals = true; }
: '@' (Letter | Digit)+
;
ASCIIStringLiteral
:
'\'' (~'\'')* '\'' ( '\'' (~'\'')* '\'' )*
;
UnicodeStringLiteral
:
'n' '\'' (~'\'')* '\'' ( '\'' (~'\'')* '\'' )*
;
// Numeric Constants
protected
HexLiteral // generated as a part of Number rule
: // "0x" ('0'..'9' | 'a'..'f')*
;

15
core/query/table.php Normal file
View file

@ -0,0 +1,15 @@
<?php
/**
* Êëàññ òàáëèöû
*/
class Table
{
public $type = 'simple';
public $name;
public $alias;
public $join;
public $condition;
}
?>

25
core/registry.php Normal file
View file

@ -0,0 +1,25 @@
<?php
/**
* http://www.patternsforphp.com/wiki/Registry
* http://www.patternsforphp.com/wiki/Singleton
* http://www.phppatterns.com/docs/design/the_registry?s=registry
*/
require_once 'core/settings.php';
class Registry extends Settings
{
static $instance = null;
/**
*/
static public function getInstance ()
{
if (self::$instance == null) {
self::$instance = new Registry();
}
return self::$instance;
}
}
?>

37
core/safecollection.php Normal file
View file

@ -0,0 +1,37 @@
<?php
require_once 'core/collection.php';
require_once 'FirePHPCore/fb.php';
class SafeCollection extends Collection
{
protected function _clean()
{
if(get_magic_quotes_gpc()) {
$this->data = $this->_stripSlashes($this->data);
}
$this->data = $this->data;
}
function import(array $data)
{
parent::import($data);
$this->_clean();
}
/**
* Strip slashes code from php.net website.
*
* @param mixed $value
* @return array
*/
protected function _stripSlashes($value)
{
if(is_array($value)) {
return array_map(array($this,'_stripSlashes'), $value);
} else {
return stripslashes($value);
}
}
}

View file

@ -0,0 +1,85 @@
<?php
/**
* Èçâëåêàåò òåêñò èç HTML äîêóìåíòà
*/
function stripText($document)
{
$search = array("'<script[^>]*?>.*?</script>'si" => "", // strip out javascript
"'<[\/\!]*?[^<>]*?>'si" => "", // strip out html tags
"'([\r\n])[\s]+'" => "\\1", // strip out white space
"'&(quot|#34|#034|#x22);'i" => "\"", // replace html entities
"'&(amp|#38|#038|#x26);'i" => "&", // added hexadecimal values
"'&(lt|#60|#060|#x3c);'i" => ">",
"'&(gt|#62|#062|#x3e);'i" => "<",
"'&(nbsp|#160|#xa0);'i" => " ",
"'&(iexcl|#161);'i" => chr(161),
"'&(cent|#162);'i" => chr(162),
"'&(pound|#163);'i" => chr(163),
"'&(copy|#169);'i" => chr(169),
"'&(reg|#174);'i" => chr(174),
"'&(deg|#176);'i" => chr(176));
$text = preg_replace(array_keys($search), array_values($search), $document);
return $text;
}
/**
* Ðàçäåëåíèå òåêñòà íà ìàññèâ ñëîâ
*/
function tokenize ($document)
{
$array = preg_split("/[\W]+/", $document);
return $array;
}
/**
* Èùåò îäèí èç ñèìâîëîâ ñ êîíöà ñòðîêè
*
* @param string $haystack
* @param array $needle Ìàññèâ ñèìâîëîâ äëÿ ïîèñêà
* @param int $offset Ñìåùåíèå îò íà÷àëà ñòðîêè
*
* @return int Ïîçèöèþ ïåðâîãî ñîâïàäåíèÿ
*/
function indexRight ($haystack, $needle, $offset = 0)
{
if ((bool)$offset === false) $offset = 0;
while ($offset >= 0) {
if (in_array ($haystack[$offset], $needle)) {
return $offset;
}
$offset --;
}
return false;
}
/**
* Èùåò îäèí èç ñèìâîëîâ ñ íà÷àëà ñòðîêè
*
* @param string $haystack
* @param array $needle Ìàññèâ ñèìâîëîâ äëÿ ïîèñêà
* @param int $offset Ñìåùåíèå îò íà÷àëà ñòðîêè
*
* @return int Ïîçèöèþ ïåðâîãî ñîâïàäåíèÿ
*/
function indexLeft ($haystack, $needle, $offset = 0)
{
if ($offset < 0) return false;
while ($offset < strlen($haystack)) {
if ((is_callable($needle) && call_user_func ($needle, $haystack[$offset]))
|| (is_array ($needle) && in_array ($haystack[$offset], $needle))) {
return $offset;
}
$offset ++;
}
return false;
}
function not_ctype_alpha ($ch)
{
return !ctype_alpha($ch);
}
?>

86
core/search/index.php Normal file
View file

@ -0,0 +1,86 @@
<?php
require_once 'core/search/htmlhelper.php';
require_once 'core/search/stemmer.php';
require_once 'core/path.php';
/**
* Èíäåêñèðîâàíèå ôàéëîâ
*/
class Index
{
const ARRAY_FILE = 0;
const ARRAY_TEXT = 1;
public $index = array ();
public $text = array ();
protected $count = 0;
function getTitle ($content) {
$title = "'<title[^>]*?>(.*?)</title>'si";
preg_match($title, $content, $matches);
if(isset($matches[1])) {
return $matches[1];
}
return "";
}
// Âûáèðàåì îñíîâó ñëîâà
function clean ($word)
{
return Stemmer::russian(strtolower($word));
}
function process ($base, $files)
{
$path = new Path($base);
// Ñïèñîê äîêóìåíòîâ
foreach ($path->getContentRec($files) as $file) {
$content = file_get_contents ($file);
$text = stripText($content);
// $title = self::getTitle ($content);
$title = pathinfo($file, PATHINFO_BASENAME);
// echo $file, "\n";
// Ñïèñîê ñëîâ â äîêóìåíòå
$list = tokenize($text);
foreach ($list as $word) {
$preword = self::clean($word);
if (isset($this->index[$preword])) {
$index = $this->index[$preword];
if ( ! in_array ($this->count, $index)) $this->index[$preword] [] = $this->count;
} else {
// Íå çàïèñûâàåì ñëîâà äëèííà êîòîðûõ ìåíüøå 2
if (strlen($preword) > 1) {
$this->index[$preword] = array ($this->count);
}
}
}
$this->text [] = array ($title, $path->relPath ($file), $text);
$this->count ++;
}
ksort($this->index);
}
/**
* Ñîõðàíåíèå ðåçóëüòàòà ïîèñêà
*/
function saveData ($file)
{
$file = fopen($file, "w");
// Êîëè÷åñòâî ñëîâ è òåêñòîâ
fwrite ($file, pack("SS", count($this->index), count($this->text)));
foreach ($this->index as $word => $value) {
$length = strlen($word);
array_unshift ($value, "SSa*S*", $length, count($value), $word);
fwrite($file, call_user_func_array ('pack', $value));
}
foreach ($this->text as $text) {
fwrite($file, pack("SSSa*a*a*",
strlen($text[0]), strlen($text[1]), strlen($text[2])
, $text[0], $text[1], $text[2]));
}
}
}
?>

93
core/search/lexer.php Normal file
View file

@ -0,0 +1,93 @@
<?php
/**
* Ðàçáèðâåò ñòðîêó çàïðîñà íà òîêåíû
*/
class Lexer
{
const TOKEN_NOT = 1;
const TOKEN_OR = 2;
const TOKEN_LPAREN = 3;
const TOKEN_RPAREN = 4;
const TOKEN_AND = 5;
const TOKEN_WORD = 6;
const TOKEN_EOL = 7;
protected $src;
private $offset = 0;
public $token;
public function __construct ()
{
}
function setSource ($src)
{
$this->src = $src;
$this->offset;
}
private function skipSpace ()
{
while (!$this->isEOL() && $this->getChar() == " ") {
$this->offset++;
}
}
private function getChar ()
{
return $this->src [$this->offset];
}
/**
* Ïðîâåðÿåò íà êîíåö ñòðîêè
*/
private function isEOL () {
return $this->offset >= strlen($this->src);
}
/**
* Îäíîñèìâîëüíûé òîêåí
*/
private function easyToken () {
$ch = $this->getChar ();
switch ($ch) {
case '~': $token = array(self::TOKEN_NOT, $ch); break;
case '|': $token = array(self::TOKEN_OR, $ch); break;
case '(': $token = array(self::TOKEN_LPAREN, $ch); break;
case ')': $token = array(self::TOKEN_RPAREN, $ch); break;
case '&': $token = array(self::TOKEN_AND, $ch); break;
default:
$this->offset++;
$token = $this->getToken();
}
$this->offset++;
return $token;
}
/**
* Âîçâðàùàåò ñëåäóþùèé òîêåí
*/
public function getToken ()
{
$this->skipSpace ();
if ($this->isEOL()) {
return array(self::TOKEN_EOL, "");
}
if (ctype_alpha($this->getChar())) {
$start = $this->offset;
while (!$this->isEOL() && ctype_alpha($this->getChar())) {
$this->offset ++;
}
return array(self::TOKEN_WORD, substr ($this->src, $start, $this->offset-$start));
}
return $this->easyToken();
}
public function nextToken ()
{
$this->token = $this->getToken();
}
}
?>

98
core/search/search.php Normal file
View file

@ -0,0 +1,98 @@
<?php
require_once 'core/search/lexer.php';
require_once 'core/functions.php';
/**
* Ïîèñê â èíäåêñå
*/
class Search
{
private $lexer;
private $index;
function __construct ($index)
{
$this->lexer = new Lexer();
$this->index = $index;
$this->op = array ($this, 'Op');
$this->binary = array ($this, 'binaryOp');
$this->union = array ($this, 'union');
$this->intersection = lcurry($this->op, 'array_uintersect', $this->union);
$this->notQuery = lcurry ($this->binary, Lexer::TOKEN_NOT,
lcurry($this->op, 'array_udiff', 'array_udiff'), array ($this, 'easyQuery'));
$this->orQuery = lcurry ($this->binary, Lexer::TOKEN_OR,
lcurry($this->op, $this->union, $this->union), $this->notQuery);
$this->andQuery = lcurry ($this->binary, Lexer::TOKEN_AND, $this->intersection, $this->orQuery);
}
function union ($a, $b, $callback)
{
return array_merge($a, $b);
}
function Eq ($a, $b)
{
return $a == $b;
}
function Op ($files, $words, $a, $b) {
return array (
'words' => call_user_func ($words, $a['words'], $b['words'], array ($this, 'eq')),
'files' => call_user_func ($files, $a['files'], $b['files'], array ($this, 'eq'))
);
}
public function getQuery ($source)
{
$this->lexer->setSource ($source);
$this->lexer->nextToken();
return $this->topQuery();
}
function topQuery ()
{
$result = call_user_func ($this->andQuery);
while ($this->lexer->token[0] == Lexer::TOKEN_LPAREN) {
$result = call_user_func ($this->intersection, $result, call_user_func ($this->andQuery));
}
return $result;
}
function easyQuery ()
{
$result = null;
if ($this->lexer->token[0] == Lexer::TOKEN_LPAREN) {
$this->lexer->nextToken ();
$result = $this->topQuery ();
if ($this->lexer->token[0] == Lexer::TOKEN_RPAREN) {
$this->lexer->nextToken ();
}
return $result;
} else {
$result = call_user_func ($this->index, $this->lexer->token[1]);
$this->lexer->nextToken ();
return $result;
}
}
/**
* @param int $type Òèï ëåêñåìû
* @param function $op Ôóíêöèÿ ïðè ñîâïàäåíèè òèïà ëåêñåìû ïðè çàïðîñå
* @param function $next Ñëåäóþùèé îáðàáîò÷èê çàïðîñà
*/
function binaryOp ($type, $op, $next)
{
$result = call_user_func($next);
while ($this->lexer->token[0] == $type) {
$this->lexer->nextToken();
$result = call_user_func($op, $result, call_user_func ($next));
}
return $result;
}
}
?>

102
core/search/searcher.php Normal file
View file

@ -0,0 +1,102 @@
<?php
require_once 'core/search/search.php';
require_once 'core/search/htmlhelper.php';
require_once 'core/search/stemmer.php';
class Searcher {
/* protected */ public $index;
protected $text;
protected $search;
public function __construct ()
{
// Ìîæåò ïåðåäàâàòü îáüåêò ìåòîä ïî óìëî÷àíèþ getWordStat??
$this->search = new Search (array ($this, 'getWord'));
}
/**
* ×èòàåò ñîäåðæèìîå èíäåêñíîãî ôàéëà
*
* @param string $file Èìÿ ôàéëà
*/
function setSource ($fileName)
{
$file = fopen($fileName, "r");
$words = fread($file, 4);
$all = unpack("Swords/Stexts", $words);
for ($i = 0; $i < $all['words']; $i++) {
$pos = fread($file, 4);
$size = unpack("Sword/Sindex", $pos);
$word = fread($file, $size['word']);
$index = unpack("S*", fread($file, $size['index']*2));
$this->index[$word] = $index;
}
for ($i = 0; $i < $all['texts']; $i++) {
$pos = fread($file, 6);
$size = unpack("Stitle/Surl/Stext", $pos);
//
$title = fread($file, $size['title']);
$url = fread($file, $size['url']);
$text = fread($file, $size['text']);
$this->text [] = array ($title, $url, $text);
}
}
// Ïî ñëîâó âîçâðàùàåì ñïèñîê ôàéëîâ è ñëîâî
public function getWord ($word)
{
$preword = Stemmer::russian($word); // Index?? -> clean
if (isset($this->index[$preword])) { // Search??
return array ('files' => $this->index[$preword], 'words' => array ($preword));
}
return array ('files' => array (), 'words' => array ());
}
/**
* Ñïèñîê äîêóìåíòîâ â êîòîðûõ âñòå÷àåòñÿ ñëîâî
*
*/
function getResult (&$query)
{
$result = array ();
$word = $query['words'];
$list = $query['files'];
//
foreach ($list as $n) {
$result [] = array (
'title' => $this->text[$n][0],
'file' => $this->text[$n][1],
'text' => self::getSlice ($word[0], $this->text[$n][2]));
}
return $result;
}
/**
* ×àñòü äîêóìåíòà â êîòîðîì âñòðå÷àåòñÿ ñëîâî
*
* @param $word Ñëîâî
* @param $text Òåêñò ñîäåðæàùèé ñëîâî
*/
function getSlice ($word, $text)
{
$pos = stripos($text, $word);
$offset = max(max ($pos-100, indexRight($text, array ("."), $pos) + 1), 0);
$real = substr($text, $pos, strlen($word)) ;
return substr($text, $offset, $pos - $offset)
. "<span style='color: red'>" . $real . "</span>" . substr ($text, $pos + strlen($word), 100);
}
/**
* Ïîèñê ïî çàïðîñó
*
*/
function search ($query)
{
$result = $this->search->getQuery($query);
return $this->getResult($result);
}
}
?>

181
core/search/stemmer.php Normal file
View file

@ -0,0 +1,181 @@
<?php
/*
* PHP5 implementation of Martin Porter's stemming algorithm for Russian language.
* Written on a cold winter evening close to the end of 2005 by Dennis Kreminsky (etranger at etranger dot ru)
* Use the code freely, but don't hold me responsible if it breaks whatever it might break.
*
*/
define ('CHAR_LENGTH', '1'); // all Russian characters take 2 bytes in UTF-8, so instead of using (not supported by default) mb_*
// string functions, we use the standard ones with a dirty char-length trick.
// Should you want to use WIN-1251 (or any other charset), convert this source file to that encoding
// and then change CHAR_LENGTH to the proper value, which is likely to be '1' then.
//
class Stemmer {
static public function russian($word)
{
$a = self::rv($word);
$start = $a[0];
$rv = $a[1];
$rv = self::step1($rv);
$rv = self::step2($rv);
$rv = self::step3($rv);
$rv = self::step4($rv);
return $start.$rv;
}
static private function rv($word)
{
$vowels = array('à','å','è','î','ó','û','ý','þ','ÿ');
$flag = 0;
$rv = '';
$start = '';
for ($i=0; $i<strlen($word); $i+=CHAR_LENGTH) {
if ($flag==1)
$rv .= substr($word, $i, CHAR_LENGTH);
else
$start .= substr($word, $i, CHAR_LENGTH);
if (array_search(substr($word,$i,CHAR_LENGTH), $vowels) !== false)
$flag=1;
}
return array($start,$rv);
}
static function substitute ($word, &$suffix_list)
{
foreach ($suffix_list as $suffix) {
if (self::has_suffix($word, $suffix)) {
$word = self::cut_suffix($word, $suffix);
}
}
return $word;
}
static function has_suffix ($word, $suffix)
{
return substr($word, -(strlen($suffix))) == $suffix;
}
static function has_aya ($word, $suffix)
{
return (substr($word,-strlen($suffix)-CHAR_LENGTH,CHAR_LENGTH)=='à' || substr($word,-strlen($suffix)-CHAR_LENGTH,CHAR_LENGTH)=='ÿ');
}
static function cut_suffix ($word, $suffix)
{
return substr($word, 0, strlen($word) - strlen($suffix));
}
static private function step1($word)
{
$perfective1 = array('â', 'âøè', 'âøèñü');
foreach ($perfective1 as $suffix) {
if (self::has_suffix($word, $suffix) && self::has_aya ($word, $suffix)) {
return self::cut_suffix($word, $suffix);
}
}
$perfective2 = array('èâ','èâøè','èâøèñü','ûâøè','ûâøèñü');
foreach ($perfective2 as $suffix) {
if (self::has_suffix($word, $suffix)) {
return self::cut_suffix($word, $suffix);
}
}
$reflexive = array('ñÿ', 'ñü');
$word = self::substitute($word, $reflexive);
$adjective = array('åå','èå','ûå','îå','èìè','ûìè','åé','èé','ûé','îé','åì','èì','ûì','îì','åãî','îãî','åìó','îìó','èõ','ûõ','óþ','þþ','àÿ','ÿÿ','îþ','åþ');
$participle2 = array('åì','íí','âø','þù','ù');
$participle1 = array('èâø','ûâø','óþù');
foreach ($adjective as $suffix) {
if (self::has_suffix($word, $suffix)) {
$word = self::cut_suffix($word, $suffix);
foreach ($participle1 as $suffix)
if (self::has_suffix($word, $suffix) && self::has_aya ($word, $suffix))
$word = self::cut_suffix($word, $suffix);
return self::substitute($word, $participle2);
}
}
$verb1 = array('ëà','íà','åòå','éòå','ëè','é','ë','åì','í','ëî','íî','åò','þò','íû','òü','åøü','ííî');
foreach ($verb1 as $suffix)
if (self::has_suffix($word, $suffix) && self::has_aya ($word, $suffix))
return self::cut_suffix($word, $suffix);
$verb2 = array('èëà','ûëà','åíà','åéòå','óéòå','èòå','èëè','ûëè','åé','óé','èë','ûë','èì','ûì','åí','èëî','ûëî','åíî','ÿò','óåò','óþò','èò','ûò','åíû','èòü','ûòü','èøü','óþ','þ');
foreach ($verb2 as $suffix)
if (self::has_suffix($word, $suffix))
return self::cut_suffix($word, $suffix);
$noun = array('à','åâ','îâ','èå','üå','å','èÿìè','ÿìè','àìè','åè','èè','è','èåé','åé','îé','èé','é','èÿì','ÿì','èåì','åì','àì','îì','î','ó','àõ','èÿõ','ÿõ','û','ü','èþ','üþ','þ','èÿ','üÿ','ÿ');
foreach ($noun as $suffix) {
if (self::has_suffix($word, $suffix))
return self::cut_suffix($word, $suffix);
}
return $word;
}
static private function step2($word)
{
if (substr($word,-CHAR_LENGTH,CHAR_LENGTH) == 'è')
$word = substr($word, 0, strlen($word)-CHAR_LENGTH);
return $word;
}
static private function step3($word)
{
$vowels = array('à','å','è','î','ó','û','ý','þ','ÿ');
$flag = 0;
$r1 = '';
$r2 = '';
for ($i=0; $i<strlen($word); $i+=CHAR_LENGTH)
{
if ($flag==2)
$r1.=substr($word, $i, CHAR_LENGTH);
if (array_search(substr($word,$i,CHAR_LENGTH), $vowels) !== false)
$flag=1;
if ($flag=1 && array_search(substr($word,$i,CHAR_LENGTH), $vowels) === false)
$flag=2;
}
$flag=0;
for ($i=0; $i<strlen($r1); $i+=CHAR_LENGTH)
{
if ($flag==2)
$r2.=substr($r1, $i, CHAR_LENGTH);
if (array_search(substr($r1,$i,CHAR_LENGTH), $vowels) !== false)
$flag=1;
if ($flag=1 && array_search(substr($r1,$i,CHAR_LENGTH), $vowels) === false)
$flag=2;
}
$derivational=array('îñò', 'îñòü');
foreach ($derivational as $suffix)
if (substr($r2,-(strlen($suffix))) == $suffix)
$word=substr($word, 0, strlen($r2)-strlen($suffix));
return $word;
}
static private function step4($word)
{
if (substr($word,-CHAR_LENGTH*2)=='íí')
$word=substr($word, 0, strlen($word)-CHAR_LENGTH);
else
{
$superlative=array('åéø', 'åéøå');
foreach ($superlative as $suffix)
if (substr($word,-(strlen($suffix))) == $suffix)
$word = substr($word, 0, strlen($word) - strlen($suffix));
if (substr($word,-CHAR_LENGTH*2) == 'íí')
$word = substr($word, 0, strlen($word) - CHAR_LENGTH);
}
// should there be a guard flag? can't think of a russian word that ends with åéøü or ííü anyways, though the algorithm states this is an "otherwise" case
if (substr($word,-CHAR_LENGTH,CHAR_LENGTH) == 'ü')
$word=substr($word, 0, strlen($word)-CHAR_LENGTH);
return $word;
}
}
?>

36
core/session.php Normal file
View file

@ -0,0 +1,36 @@
<?php
class Session
{
function get($key)
{
if (isset($_SESSION[$key])) {
return $_SESSION[$key];
}
return null;
}
function set($key, $value)
{
if (is_array($key)) {
$_SESSION[strtolower(get_class($key[0]))][$key[1]] = $value;
} else {
$_SESSION[$key] = $value;
}
}
function clean($key)
{
unset($_SESSION[$key]);
}
function start()
{
session_start();
}
function stop()
{
session_destroy();
}
}

167
core/settings.php Normal file
View file

@ -0,0 +1,167 @@
<?php
require_once 'core/collection.php';
/**
* Êëàññ ðååñòðà
* Ðååñòð îðãàíèçîâàí êàê àññîöèàòèâíûé ìíîãîìåðíûé ìàññèâ
* array( 'name1' => parameters1, 'name2' => parameters1, ... )
*
* name1, name2 ... - Èìåíà ìîäóëåé
* parameters1, parameters1 - Ìàññèâû ñ ïàðàìåòðàìè ìîäóëÿ
* Èìÿ íåîáõîäèìî ÷òîáû ïîòîì ëåãêî áûëî óäàëèòü íåíóæíûå âåòêè äåðåâà
*/
class Settings extends Collection
{
protected $file;
public function __construct ($file = null)
{
$this->file = $file;
}
/**
* ×òåíèå íàñòðîåê èç ôàéëà
*
* @param File $file
*
* @return Boolean
*/
public function read()
{
if ( !file_exists ($this->file)) return false;
// Íå include_once ò.ê ÷èòàòü íàñòðîéêè ìîæíî íåñêîëüêî ðàç
include($this->file);
if (!is_array($settings)) {
throw new Exception($this->file);
}
return $this->import($settings);
}
/**
* Çàïèñü êëþ÷à â ðååñòð (Ðååñòð ýòî ìîãîìåðíûé ìàññèâ)
*/
public function writeKey(array $key, $value)
{
// assert(count($key) >= 1);
$data = &$this->data;
while (count($key) > 1) {
$name = array_shift($key);
$data = &$data[$name];
}
// assert(count($key) == 1);
$name = array_shift($key);
if (is_array($value)) {
if (! isset($data[$name])) $data[$name] = array();
$this->merge($data[$name], $value);
} else {
$data[$name] = $value;
}
}
/**
* Îáíîâëÿåò ìàññèâ â ñîîòâåòñòâèè ñî çíà÷åíèåì
*/
protected function merge(array &$data, $value)
{
foreach ($value as $key => $subvalue) {
if (is_array($subvalue)) {
if (! isset($data[$key])) $data[$key] = array();
$this->merge($data[$key], $subvalue);
} else {
$data[$key] = $subvalue;
}
}
}
/**
* ×òåíèå êëþ÷à èç ðååñòðà
* @param $args Ïóòü ê çíà÷åíèþ êëþ÷à
*/
public function readKey(array $key)
{
return $this->readKeyData($key, $this->data);
}
protected function readKeyData(array $key, $data)
{
// assert(count($key) >= 1);
while (count($key) > 1) {
$name = array_shift($key);
if (isset($data[$name])) {
$data = $data[$name];
} else {
return null;
}
}
// assert(count($key) == 1);
$name = array_shift($key);
if (isset($data[$name])) {
return $data[$name];
} else {
return null;
}
}
/**
* ×òåíèå êëþ÷à èç ðååñòðà (Ñîáèðàåò âñå êëþ÷è ñ îïðåäåëåííûì çíà÷åíèåì âî âñåõ ìîäóëÿõ)
* @param $key Ïóòü ê çíà÷åíèþ êëþ÷à âíóòðè ìîäóëÿ
*/
public function readKeyList()
{
$key = func_get_args();
$result = array();
foreach ($this->data as $name => $value) {
$output = $this->readKeyData($key, $value);
if ($output) {
$result[$name] = $output;
}
}
return $result;
}
public function removeKey($name)
{
unset($this->data[$name]);
}
public function removeNode(array $key)
{
$data = &$this->data;
while (count($key) > 1) {
$name = array_shift($key);
$data = &$data[$name];
}
$name = array_shift($key);
unset($data[$name]);
}
public function getOwner()
{
return array_keys($this->data);
}
/**
* Çàïèñü íàñòðîåê â ôàéë (Ìîæåò ïåðåèìåíîâàòü â store)
*
* @param File $file
*
* @return void
*/
public function write($file = false)
{
$result = var_export ($this->data, true);
file_put_contents (($file) ? $file : $this->file, "<?php\n\$settings = ".$result.";\n?>");
}
/**
* Ñïèñîê ìîäóëåé
*/
public function getModules()
{
return array_keys($this->data);
}
}

59
core/setup.php Normal file
View file

@ -0,0 +1,59 @@
<?php
require_once 'core/path.php';
require_once 'creole/util/sql/SQLStatementExtractor.php';
/**
* Îáðàáîòêà ôàéëîâ äëÿ óñòàíîâêè
*/
class Setup
{
/**
* Ñîäåðæèìîå PHP ôàéëà
*/
static function fileContent($file, array $tpl)
{
ob_start();
include $file;
$result = ob_get_contents();
ob_clean();
return $result;
}
/**
* Êîïèðóåò ôàéëû øàáëîííîé äèðåêòîðèè
*/
static function copyTemplatePath($srcPath, $dstPath, array $tpl, $tplFile = 'tpl')
{
$out = new Path($srcPath);
$path = new Path($dstPath);
$files = $path->getContentRec(null, array(".svn"));
foreach ($files as $file) {
if (Path::getExtension($file) == $tplFile) {
// Øàáëîí
$dst = $out->append($path->relPath (Path::skipExtension($file)));
Path::prepare($dst);
file_put_contents($dst, self::fileContent($file, $tpl));
} else {
// Îáû÷íûé ôàéë
$dst = $out->append($path->relPath ($file));
Path::prepare($dst);
copy($file, $dst);
}
}
}
/**
* Âûïîëíåíèå Ñïèñêà SQL êîìàíä
*/
static function batchSQL(Connection $conn, $file)
{
$stmtList = SQLStatementExtractor::extractFile ($file);
foreach ($stmtList as $stmt) {
$conn->executeQuery ($stmt);
}
}
}
?>

58
core/shortcut.php Normal file
View file

@ -0,0 +1,58 @@
<?php
/**
* Êëàññ äëÿ êîðîòêîãî äîñòóïà ê ôàéëàì / ïàïêàì
*/
class Shortcut
{
static $instance = null;
public $variables = array();
public $list = array();
// Singleton pattern
static public function getInstance ()
{
if (self::$instance == null) {
self::$instance = new Shortcut();
}
return self::$instance;
}
/**
* Äîáàâëÿåò ÿðëûê ñ èìåíåì $prefix
* Ïóòü ìîæåò ñîäåðæàòü ïåðåìåííûå
*/
public function addUrl($prefix, $path)
{
$this->list [$prefix] = $path;
}
/**
*
*/
public function addVar($name, $value)
{
$this->variables['$' . $name] = $value;
}
/**
* Âîçâðàùàåò ïóòü ïî èìåíè ÿðëûêà
*/
static function getUrl ($prefix, $name = null, $name1 = false)
{
$shortcut = self::getInstance();
$names = $shortcut->variables;
if ($name) {
$names['$name'] = $name;
}
if ($name1) {
$names['$name1'] = $name1;
}
if (isset($shortcut->list[$prefix])) {
return strtr($shortcut->list[$prefix], $names);
}
return false;
}
}
?>

58
core/sort.php Normal file
View file

@ -0,0 +1,58 @@
<?php
class SortRecord
{
function __construct($key, $mode, $order)
{
$this->key = $key;
$this->order = ((boolean)($order) === false) ? 1 : -1;
$this->mode = $mode;
}
function compare($a, $b)
{
if($a[$this->key] == $b[$this->key]) {
return 0;
}
return ($a[$this->key] > $b[$this->key]) ? $this->order : -$this->order;
}
function compareKeys($a, $b)
{
if($a->{$this->key} == $b->{$this->key}) {
return 0;
}
return ($a->{$this->key} > $b->{$this->key}) ? $this->order : -$this->order;
}
function sort(&$list)
{
return usort($list, array($this, 'compare'));
}
function sortKeys(&$list)
{
return usort($list, array($this, 'compareKeys'));
}
function group(&$list, $key, $types)
{
$groups = array();
foreach ($types as $name) {
$groups[$name] = array();
}
$groups['_any_'] = array();
foreach ($list as $item) {
if (isset($groups[$item[$key]])) {
$groups[$item[$key]][] = $item;
} else {
$groups['_any_'][] = $item;
}
}
$result = array();
foreach ($groups as $value) {
$result = array_merge($result, $value);
}
$list = $result;
}
}

100
core/spell.php Normal file
View file

@ -0,0 +1,100 @@
<?php
require_once 'core/search/htmlhelper.php';
/**
* Ôóíêöèè äëÿ ïðîâåðêè îðôîãðàôèè
* rename Spell -> SpellHelper ??
*/
class Spell
{
private $pspell;
public $autocorrect = false;
public function __construct ($language, $encoding)
{
$this->pspell = pspell_new($language, '', '', $encoding, PSPELL_NORMAL);
}
function spellCheckWord ($word)
{
$word = $word[0];
// Ignore ALL CAPS
if (preg_match('/^[A-Z0-9]*$/', $word)) return $word;
// Return dictionary words
if (pspell_check($this->pspell, $word))
return $word;
// Auto-correct with the first suggestion, color green
if ($this->autocorrect && $suggestions = pspell_suggest($this->pspell, $word))
return '<span class="spell-suggest">' . current($suggestions) . '</span>';
// No suggestions, color red
return '<span class="spell-nosuggest">' . $word . '</span>';
}
function isGoodWord ($word)
{
// Ignore ALL CAPS
if (preg_match('/^[A-Z]*$/', $word)) return true;
if (preg_match('/^[0-9]*$/', $word)) return true;
// Return dictionary words
if (pspell_check($this->pspell, $word))
return true;
return false;
}
function suggest ($string)
{
return preg_replace_callback('/\b\w+\b/', array($this, 'spellCheckWord'), $string);
}
/**
* Âûçûâàåò ôóíêöèþ äëÿ êàæäîãî íàéäåííîãî ñëîâà
*/
function eachWord ($call, $string)
{
$begin = indexLeft ($string, 'ctype_alpha', 0);
while ($begin !== false) {
$end = indexLeft ($string, 'not_ctype_alpha', $begin);
call_user_func ($call, $string, $begin, $end);
$begin = indexLeft ($string, 'ctype_alpha', $end);
}
return false;
}
/**
* Ïðîâåðÿåò ñëîâî íà ñîîòâåòñòâèå ñî ñëîâàðåì
*
*/
function doWord (&$string, $begin, $end)
{
$word = substr($string, $begin, $end - $begin);
if (! $this->isGoodWord ($word)) {
$start = max(indexLeft ($string, 'not_ctype_alpha', $begin - 100), 0);
$offset = indexLeft ($string, 'not_ctype_alpha', $end + 100);
if (! $offset) {
$offset = strlen($string);
}
$length = $offset - $start;
throw new Exception ($this->suggest(substr($string, $start, $length)));
}
}
/**
* ×àñòü òåêñòà ñîäåðæàùèé íåïðàâèëüíîå ñëîâî
*/
function getError ($string)
{
try {
self::eachWord (array ($this, 'doWord'), $string);
} catch (Exception $e) {
return $e->getMessage();
}
return false;
}
}
?>

741
core/spyc.php Normal file
View file

@ -0,0 +1,741 @@
<?php
/**
* Spyc -- A Simple PHP YAML Class
* @version 0.3
* @author Chris Wanstrath <chris@ozmm.org>
* @author Vlad Andersen <vlad@oneiros.ru>
* @link http://spyc.sourceforge.net/
* @copyright Copyright 2005-2006 Chris Wanstrath
* @license http://www.opensource.org/licenses/mit-license.php MIT License
* @package Spyc
*/
/**
* The Simple PHP YAML Class.
*
* This class can be used to read a YAML file and convert its contents
* into a PHP array. It currently supports a very limited subsection of
* the YAML spec.
*
* Usage:
* <code>
* $parser = new Spyc;
* $array = $parser->load($file);
* </code>
* @package Spyc
*/
class Spyc {
/**#@+
* @access private
* @var mixed
*/
private $_haveRefs;
private $_allNodes;
private $_allParent;
private $_lastIndent;
private $_lastNode;
private $_inBlock;
private $_isInline;
private $_dumpIndent;
private $_dumpWordWrap;
private $_containsGroupAnchor = false;
private $_containsGroupAlias = false;
private $path;
private $result;
private $LiteralBlockMarkers = array ('>', '|');
private $LiteralPlaceHolder = '___YAML_Literal_Block___';
private $SavedGroups = array();
/**#@+
* @access public
* @var mixed
*/
public $_nodeId;
/**
* Load YAML into a PHP array statically
*
* The load method, when supplied with a YAML stream (string or file),
* will do its best to convert YAML in a file into a PHP array. Pretty
* simple.
* Usage:
* <code>
* $array = Spyc::YAMLLoad('lucky.yaml');
* print_r($array);
* </code>
* @access public
* @return array
* @param string $input Path of YAML file or string containing YAML
*/
public static function YAMLLoad($input) {
$Spyc = new Spyc;
return $Spyc->load($input);
}
/**
* Dump YAML from PHP array statically
*
* The dump method, when supplied with an array, will do its best
* to convert the array into friendly YAML. Pretty simple. Feel free to
* save the returned string as nothing.yaml and pass it around.
*
* Oh, and you can decide how big the indent is and what the wordwrap
* for folding is. Pretty cool -- just pass in 'false' for either if
* you want to use the default.
*
* Indent's default is 2 spaces, wordwrap's default is 40 characters. And
* you can turn off wordwrap by passing in 0.
*
* @access public
* @return string
* @param array $array PHP array
* @param int $indent Pass in false to use the default, which is 2
* @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
*/
public static function YAMLDump($array,$indent = false,$wordwrap = false) {
$spyc = new Spyc;
return $spyc->dump($array,$indent,$wordwrap);
}
/**
* Dump PHP array to YAML
*
* The dump method, when supplied with an array, will do its best
* to convert the array into friendly YAML. Pretty simple. Feel free to
* save the returned string as tasteful.yaml and pass it around.
*
* Oh, and you can decide how big the indent is and what the wordwrap
* for folding is. Pretty cool -- just pass in 'false' for either if
* you want to use the default.
*
* Indent's default is 2 spaces, wordwrap's default is 40 characters. And
* you can turn off wordwrap by passing in 0.
*
* @access public
* @return string
* @param array $array PHP array
* @param int $indent Pass in false to use the default, which is 2
* @param int $wordwrap Pass in 0 for no wordwrap, false for default (40)
*/
public function dump($array,$indent = false,$wordwrap = false) {
// Dumps to some very clean YAML. We'll have to add some more features
// and options soon. And better support for folding.
// New features and options.
if ($indent === false or !is_numeric($indent)) {
$this->_dumpIndent = 2;
} else {
$this->_dumpIndent = $indent;
}
if ($wordwrap === false or !is_numeric($wordwrap)) {
$this->_dumpWordWrap = 40;
} else {
$this->_dumpWordWrap = $wordwrap;
}
// New YAML document
$string = "---\n";
// Start at the base of the array and move through it.
foreach ($array as $key => $value) {
$string .= $this->_yamlize($key,$value,0);
}
return $string;
}
/**
* Attempts to convert a key / value array item to YAML
* @access private
* @return string
* @param $key The name of the key
* @param $value The value of the item
* @param $indent The indent of the current node
*/
private function _yamlize($key,$value,$indent) {
if (is_array($value)) {
// It has children. What to do?
// Make it the right kind of item
$string = $this->_dumpNode($key,NULL,$indent);
// Add the indent
$indent += $this->_dumpIndent;
// Yamlize the array
$string .= $this->_yamlizeArray($value,$indent);
} elseif (!is_array($value)) {
// It doesn't have children. Yip.
$string = $this->_dumpNode($key,$value,$indent);
}
return $string;
}
/**
* Attempts to convert an array to YAML
* @access private
* @return string
* @param $array The array you want to convert
* @param $indent The indent of the current level
*/
private function _yamlizeArray($array,$indent) {
if (is_array($array)) {
$string = '';
foreach ($array as $key => $value) {
$string .= $this->_yamlize($key,$value,$indent);
}
return $string;
} else {
return false;
}
}
/**
* Returns YAML from a key and a value
* @access private
* @return string
* @param $key The name of the key
* @param $value The value of the item
* @param $indent The indent of the current node
*/
private function _dumpNode($key,$value,$indent) {
// do some folding here, for blocks
if (strpos($value,"\n") !== false || strpos($value,": ") !== false || strpos($value,"- ") !== false) {
$value = $this->_doLiteralBlock($value,$indent);
} else {
$value = $this->_doFolding($value,$indent);
}
if (is_bool($value)) {
$value = ($value) ? "true" : "false";
}
$spaces = str_repeat(' ',$indent);
if (is_int($key)) {
// It's a sequence
$string = $spaces.'- '.$value."\n";
} else {
// It's mapped
$string = $spaces.$key.': '.$value."\n";
}
return $string;
}
/**
* Creates a literal block for dumping
* @access private
* @return string
* @param $value
* @param $indent int The value of the indent
*/
private function _doLiteralBlock($value,$indent) {
$exploded = explode("\n",$value);
$newValue = '|';
$indent += $this->_dumpIndent;
$spaces = str_repeat(' ',$indent);
foreach ($exploded as $line) {
$newValue .= "\n" . $spaces . trim($line);
}
return $newValue;
}
/**
* Folds a string of text, if necessary
* @access private
* @return string
* @param $value The string you wish to fold
*/
private function _doFolding($value,$indent) {
// Don't do anything if wordwrap is set to 0
if ($this->_dumpWordWrap === 0) {
return $value;
}
if (strlen($value) > $this->_dumpWordWrap) {
$indent += $this->_dumpIndent;
$indent = str_repeat(' ',$indent);
$wrapped = wordwrap($value,$this->_dumpWordWrap,"\n$indent");
$value = ">\n".$indent.$wrapped;
}
return $value;
}
/* LOADING FUNCTIONS */
private function load($input) {
$Source = $this->loadFromSource($input);
if (empty ($Source)) return array();
$this->path = array();
$this->result = array();
for ($i = 0; $i < count($Source); $i++) {
$line = $Source[$i];
$lineIndent = $this->_getIndent($line);
$this->path = $this->getParentPathByIndent($lineIndent);
$line = $this->stripIndent($line, $lineIndent);
if ($this->isComment($line)) continue;
if ($literalBlockStyle = $this->startsLiteralBlock($line)) {
$line = rtrim ($line, $literalBlockStyle . "\n");
$literalBlock = '';
$line .= $this->LiteralPlaceHolder;
while ($this->literalBlockContinues($Source[++$i], $lineIndent)) {
$literalBlock = $this->addLiteralLine($literalBlock, $Source[$i], $literalBlockStyle);
}
$i--;
}
$lineArray = $this->_parseLine($line);
if ($literalBlockStyle)
$lineArray = $this->revertLiteralPlaceHolder ($lineArray, $literalBlock);
$this->addArray($lineArray, $lineIndent);
}
return $this->result;
}
private function loadFromSource ($input) {
if (!empty($input) && strpos($input, "\n") === false && file_exists($input))
return file($input);
$foo = explode("\n",$input);
foreach ($foo as $k => $_) {
$foo[$k] = trim ($_, "\r");
}
return $foo;
}
/**
* Finds and returns the indentation of a YAML line
* @access private
* @return int
* @param string $line A line from the YAML file
*/
private function _getIndent($line) {
if (!preg_match('/^ +/',$line,$match)) return 0;
if (!empty($match[0])) return strlen ($match[0]);
return 0;
}
/**
* Parses YAML code and returns an array for a node
* @access private
* @return array
* @param string $line A line from the YAML file
*/
private function _parseLine($line) {
if (!$line) return array();
$line = trim($line);
if (!$line) return array();
$array = array();
if ($group = $this->nodeContainsGroup($line)) {
$this->addGroup($line, $group);
$line = $this->stripGroup ($line, $group);
}
if ($this->startsMappedSequence($line))
return $this->returnMappedSequence($line);
if ($this->startsMappedValue($line))
return $this->returnMappedValue($line);
if ($this->isArrayElement($line))
return $this->returnArrayElement($line);
return $this->returnKeyValuePair($line);
}
/**
* Finds the type of the passed value, returns the value as the new type.
* @access private
* @param string $value
* @return mixed
*/
private function _toType($value) {
if (strpos($value, '#') !== false)
$value = trim(preg_replace('/#(.+)$/','',$value));
if (preg_match('/^("(.*)"|\'(.*)\')/',$value,$matches)) {
$value = (string)preg_replace('/(\'\'|\\\\\')/',"'",end($matches));
$value = preg_replace('/\\\\"/','"',$value);
} elseif (preg_match('/^\\[(.+)\\]$/',$value,$matches)) {
// Inline Sequence
// Take out strings sequences and mappings
$explode = $this->_inlineEscape($matches[1]);
// Propogate value array
$value = array();
foreach ($explode as $v) {
$value[] = $this->_toType($v);
}
} elseif (strpos($value,': ')!==false && !preg_match('/^{(.+)/',$value)) {
// It's a map
$array = explode(': ',$value);
$key = trim($array[0]);
array_shift($array);
$value = trim(implode(': ',$array));
$value = $this->_toType($value);
$value = array($key => $value);
} elseif (preg_match("/{(.+)}$/",$value,$matches)) {
// Inline Mapping
// Take out strings sequences and mappings
$explode = $this->_inlineEscape($matches[1]);
// Propogate value array
$array = array();
foreach ($explode as $v) {
$array = $array + $this->_toType($v);
}
$value = $array;
} elseif (strtolower($value) == 'null' or $value == '' or $value == '~') {
$value = null;
} elseif (preg_match ('/^[0-9]+$/', $value)) {
$value = (int)$value;
} elseif (in_array(strtolower($value),
array('true', 'on', '+', 'yes', 'y'))) {
$value = true;
} elseif (in_array(strtolower($value),
array('false', 'off', '-', 'no', 'n'))) {
$value = false;
} elseif (is_numeric($value)) {
$value = (float)$value;
} else {
// Just a normal string, right?
// $value = trim(preg_replace('/#(.+)$/','',$value));
}
// print_r ($value);
return $value;
}
/**
* Used in inlines to check for more inlines or quoted strings
* @access private
* @return array
*/
private function _inlineEscape($inline) {
// There's gotta be a cleaner way to do this...
// While pure sequences seem to be nesting just fine,
// pure mappings and mappings with sequences inside can't go very
// deep. This needs to be fixed.
$saved_strings = array();
// Check for strings
$regex = '/(?:(")|(?:\'))((?(1)[^"]+|[^\']+))(?(1)"|\')/';
if (preg_match_all($regex,$inline,$strings)) {
$saved_strings = $strings[0];
$inline = preg_replace($regex,'YAMLString',$inline);
}
unset($regex);
// Check for sequences
if (preg_match_all('/\[(.+)\]/U',$inline,$seqs)) {
$inline = preg_replace('/\[(.+)\]/U','YAMLSeq',$inline);
$seqs = $seqs[0];
}
// Check for mappings
if (preg_match_all('/{(.+)}/U',$inline,$maps)) {
$inline = preg_replace('/{(.+)}/U','YAMLMap',$inline);
$maps = $maps[0];
}
$explode = explode(', ',$inline);
// Re-add the sequences
if (!empty($seqs)) {
$i = 0;
foreach ($explode as $key => $value) {
if (strpos($value,'YAMLSeq') !== false) {
$explode[$key] = str_replace('YAMLSeq',$seqs[$i],$value);
++$i;
}
}
}
// Re-add the mappings
if (!empty($maps)) {
$i = 0;
foreach ($explode as $key => $value) {
if (strpos($value,'YAMLMap') !== false) {
$explode[$key] = str_replace('YAMLMap',$maps[$i],$value);
++$i;
}
}
}
// Re-add the strings
if (!empty($saved_strings)) {
$i = 0;
foreach ($explode as $key => $value) {
while (strpos($value,'YAMLString') !== false) {
$explode[$key] = preg_replace('/YAMLString/',$saved_strings[$i],$value, 1);
++$i;
$value = $explode[$key];
}
}
}
return $explode;
}
private function literalBlockContinues ($line, $lineIndent) {
if (!trim($line)) return true;
if ($this->_getIndent($line) > $lineIndent) return true;
return false;
}
private function addArray ($array, $indent) {
$key = key ($array);
if (!isset ($array[$key])) return false;
if ($array[$key] === array()) { $array[$key] = ''; };
$value = $array[$key];
// Unfolding inner array tree as defined in $this->_arrpath.
//$_arr = $this->result; $_tree[0] = $_arr; $i = 1;
$tempPath = Spyc::flatten ($this->path);
eval ('$_arr = $this->result' . $tempPath . ';');
if ($this->_containsGroupAlias) {
do {
if (!isset($this->SavedGroups[$this->_containsGroupAlias])) { echo "Bad group name: $this->_containsGroupAlias."; break; }
$groupPath = $this->SavedGroups[$this->_containsGroupAlias];
eval ('$value = $this->result' . Spyc::flatten ($groupPath) . ';');
} while (false);
$this->_containsGroupAlias = false;
}
// Adding string or numeric key to the innermost level or $this->arr.
if ($key)
$_arr[$key] = $value;
else {
if (!is_array ($_arr)) { $_arr = array ($value); $key = 0; }
else { $_arr[] = $value; end ($_arr); $key = key ($_arr); }
}
$this->path[$indent] = $key;
eval ('$this->result' . $tempPath . ' = $_arr;');
if ($this->_containsGroupAnchor) {
$this->SavedGroups[$this->_containsGroupAnchor] = $this->path;
$this->_containsGroupAnchor = false;
}
}
private function flatten ($array) {
$tempPath = array();
if (!empty ($array)) {
foreach ($array as $_) {
if (!is_int($_)) $_ = "'$_'";
$tempPath[] = "[$_]";
}
}
//end ($tempPath); $latestKey = key($tempPath);
$tempPath = implode ('', $tempPath);
return $tempPath;
}
private function startsLiteralBlock ($line) {
$lastChar = substr (trim($line), -1);
if (in_array ($lastChar, $this->LiteralBlockMarkers))
return $lastChar;
return false;
}
private function addLiteralLine ($literalBlock, $line, $literalBlockStyle) {
$line = $this->stripIndent($line);
$line = str_replace ("\r\n", "\n", $line);
if ($literalBlockStyle == '|') {
return $literalBlock . $line;
}
if (strlen($line) == 0) return $literalBlock . "\n";
// echo "|$line|";
if ($line != "\n")
$line = trim ($line, "\r\n ") . " ";
return $literalBlock . $line;
}
private function revertLiteralPlaceHolder ($lineArray, $literalBlock) {
foreach ($lineArray as $k => $_) {
if (substr($_, -1 * strlen ($this->LiteralPlaceHolder)) == $this->LiteralPlaceHolder)
$lineArray[$k] = rtrim ($literalBlock, " \r\n");
}
return $lineArray;
}
private function stripIndent ($line, $indent = -1) {
if ($indent == -1) $indent = $this->_getIndent($line);
return substr ($line, $indent);
}
private function getParentPathByIndent ($indent) {
if ($indent == 0) return array();
$linePath = $this->path;
do {
end($linePath); $lastIndentInParentPath = key($linePath);
if ($indent <= $lastIndentInParentPath) array_pop ($linePath);
} while ($indent <= $lastIndentInParentPath);
return $linePath;
}
private function clearBiggerPathValues ($indent) {
if ($indent == 0) $this->path = array();
if (empty ($this->path)) return true;
foreach ($this->path as $k => $_) {
if ($k > $indent) unset ($this->path[$k]);
}
return true;
}
private function isComment ($line) {
if (preg_match('/^#/', $line)) return true;
return false;
}
private function isArrayElement ($line) {
if (!$line) return false;
if ($line[0] != '-') return false;
if (strlen ($line) > 3)
if (substr($line,0,3) == '---') return false;
return true;
}
private function isHashElement ($line) {
if (!preg_match('/^(.+?):/', $line, $matches)) return false;
$allegedKey = $matches[1];
if ($allegedKey) return true;
//if (substr_count($allegedKey, )
return false;
}
private function isLiteral ($line) {
if ($this->isArrayElement($line)) return false;
if ($this->isHashElement($line)) return false;
return true;
}
private function startsMappedSequence ($line) {
if (preg_match('/^-(.*):$/',$line)) return true;
}
private function returnMappedSequence ($line) {
$array = array();
$key = trim(substr(substr($line,1),0,-1));
$array[$key] = '';
return $array;
}
private function returnMappedValue ($line) {
$array = array();
$key = trim(substr($line,0,-1));
$array[$key] = '';
return $array;
}
private function startsMappedValue ($line) {
if (preg_match('/^(.*):$/',$line)) return true;
}
private function returnKeyValuePair ($line) {
$array = array();
if (preg_match('/^(.+):/',$line,$key)) {
// It's a key/value pair most likely
// If the key is in double quotes pull it out
if (preg_match('/^(["\'](.*)["\'](\s)*:)/',$line,$matches)) {
$value = trim(str_replace($matches[1],'',$line));
$key = $matches[2];
} else {
// Do some guesswork as to the key and the value
$explode = explode(':',$line);
$key = trim($explode[0]);
array_shift($explode);
$value = trim(implode(':',$explode));
}
// Set the type of the value. Int, string, etc
$value = $this->_toType($value);
if (empty($key)) {
$array[] = $value;
} else {
$array[$key] = $value;
}
}
return $array;
}
private function returnArrayElement ($line) {
if (strlen($line) <= 1) return array(array()); // Weird %)
$array = array();
$value = trim(substr($line,1));
$value = $this->_toType($value);
$array[] = $value;
return $array;
}
private function nodeContainsGroup ($line) {
if (strpos($line, '&') === false && strpos($line, '*') === false) return false; // Please die fast ;-)
if (preg_match('/^(&[^ ]+)/', $line, $matches)) return $matches[1];
if (preg_match('/^(\*[^ ]+)/', $line, $matches)) return $matches[1];
if (preg_match('/(&[^" ]+$)/', $line, $matches)) return $matches[1];
if (preg_match('/(\*[^" ]+$)/', $line, $matches)) return $matches[1];
return false;
}
private function addGroup ($line, $group) {
if (substr ($group, 0, 1) == '&') $this->_containsGroupAnchor = substr ($group, 1);
if (substr ($group, 0, 1) == '*') $this->_containsGroupAlias = substr ($group, 1);
//print_r ($this->path);
}
private function stripGroup ($line, $group) {
$line = trim(str_replace($group, '', $line));
return $line;
}
}
?>

69
core/tabletree.php Normal file
View file

@ -0,0 +1,69 @@
<?php
/**
* Ïðåîáðàçîâàíèå äåðåâà èç ìîäåëè Plain â ìàññèâ ìàññèâîâ (Adjacency List)
*/
require_once 'core/functions.php';
define (SORT_DESC, 0); // descending
define (SORT_ASC, 1); // ascending
/**
* Âûáèðàåò âñå ñðîêè èç òàáëèöû ñ óíèêàëüíûìè çíà÷åíèÿìè êëþ÷à
* @param $name Èìÿ êëþ÷à
* @param $table Äâóõìåðíûé ìàññèâ
* @example
* key_unique_values ('name', array (array ('name' => 1), array ('name' => 2), array ('name' => 1)))
=> array (1, 2)
* @end example
*/
function key_unique_values ($name, $table) {
// Èùåì óíèêàëüíûå çíà÷åíèÿ äëÿ çàäàííîãî êëþ÷à
$keys = array ();
foreach ($table as $row) {
if (!in_array ($row[$name], $keys))
$keys[] = $row[$name];
}
return $keys;
}
/**
* Ñîðòèðîâêà äâóìåðíîãî ìàññèâà ïî çàäàííîìó êëþ÷ó
* @param $array Ìàññèâ
* @param $key Èìÿ êëþ÷à ïî çíà÷åíèþ êîòîðîãî áóäåò èäòè ñðàâíåíèå
* @return Îòñîðòèðîâàííûé ìàññèâ
*/
function sortOn($array, $key, $fn = '__cmp') {
usort ($array, rcurry($fn, $key));
//usort ($array, create_function ('$x,$y', 'return __cmp ($x, $y, "'.$key.'");'));
return $array;
}
/**
* Îáõîäèò òàáëèöó êàê äåðåâî
* @param $level Array Óðîâíè âëîæåííîñòè
* @param $table Òàáëèöà
* @param $fn Ôóíêöèÿ êîòîðàÿ ïðèìåíÿåòñÿ ê êàæäîé âåòêå äåðåâà
* $fn ($name, $index, $rows, $cc)
* @param $name Êëþ÷ óðîâíÿ
* @param $index Çíà÷åíèå êëþ÷à óðîâíÿ
* @param $rows Âñå ñòîëáöû òåêóùãî óðîâíÿ
* @parma $cc Ñòîëáöû áîëåå íèçêîãî óðîâíÿ
*/
function tableTreeWalk($level, $table, $fn) {
if (empty ($level)) return $table;
$name = array_shift ($level);
$keys = key_unique_values($name, $table);
$data = array ();
foreach ($keys as $index) {
list($rows, $table) = partition (lcurry('__index', $index, $name), $table);
// $rows = array_filter ($table, lcurry('__index', intval($index), $name));
//$rows = array_filter ($table, create_function ('$x', 'return __index ('.intval($index).', \''.$name.'\', $x);'));
$data[$index] = call_user_func ($fn, $name, $index, $rows, tableTreeWalk ($level, $rows, $fn));
}
return $data;
}

36
core/tales.php Normal file
View file

@ -0,0 +1,36 @@
<?php
/**
* Ðàñøèðåíèÿ äëÿ PHPTAL äëÿ îòîáðàæåíèÿ âðåìåíè è äàòû
* package utils
*/
class DateTime_Tales implements PHPTAL_Tales
{
static public function date ($expression, $nothrow = false)
{
return "phptal_date(".PHPTAL_TalesInternal::path ($expression).")";
}
static public function time ($expression, $nothrow = false)
{
return "phptal_time(".PHPTAL_TalesInternal::path ($expression).")";
}
}
/* Ðåãèñòðàöèÿ íîâîãî ïðåôèêñà äëÿ ïîäêëþ÷åíèÿ êîìïîíåíòà */
$registry = PHPTAL_TalesRegistry::getInstance();
$registry->registerPrefix('date', array('DateTime_Tales', 'date'));
$registry->registerPrefix('time', array('DateTime_Tales', 'time'));
function phptal_date ($e)
{
return date ("d.m.Y", $e);
}
function phptal_time ($e)
{
return date ("H:i", $e);
}
?>

123
core/tools/drawing.php Normal file
View file

@ -0,0 +1,123 @@
<?php
class Drawing
{
const ALIGN_LEFT = "left";
const ALIGN_TOP = "top";
const ALIGN_BOTTOM = "bottom";
const ALIGN_CENTER = "center";
const ALIGN_RIGHT = "right";
static function drawrectnagle(&$image, $left, $top, $width, $height, $rgb)
{
$color = imagecolorallocate($image, $rgb[0], $rgb[1], $rgb[2]);
$right = $left + $width;
$bottom = $top + $height;
imageline($image, $left, $top, $right, $top, $color);
imageline($image, $right,$top, $right, $bottom, $color);
imageline($image, $left, $bottom, $right, $bottom, $color);
imageline($image, $left, $top, $left, $bottom, $color);
}
/**
* http://ru2.php.net/imagettftext
*/
static function imagettftextbox(&$image, $size, $angle, $left, $top, $color, $font, $text,
$max_width, $max_height, $align, $valign)
{
// echo var_dump($font);
// echo $left,"\n", $top, "\n";
// echo $max_width,"\n", $max_height, "\n";
// self::drawrectnagle($image, $left, $top, $max_width, $max_height, array(0xFF,0,0));
$text_lines = explode("\n", $text); // Supports manual line breaks!
$lines = array();
$line_widths = array();
$largest_line_height = 0;
foreach ($text_lines as $block) {
$current_line = ''; // Reset current line
$words = explode(' ', $block); // Split the text into an array of single words
$first_word = true;
$last_width = 0;
for ($i = 0; $i < count($words); $i++) {
$item = $words[$i];
// echo "->", $font, "\n";
$dimensions = imagettfbbox($size, $angle, $font, $current_line . ($first_word ? '' : ' ') . $item);
$line_width = $dimensions[2] - $dimensions[0];
$line_height = $dimensions[1] - $dimensions[7];
$largest_line_height = max($line_height, $largest_line_height);
if ($line_width > $max_width && !$first_word) {
$lines[] = $current_line;
$line_widths[] = $last_width ? $last_width : $line_width;
$current_line = $item;
} else {
$current_line .= ($first_word ? '' : ' ') . $item;
}
if ($i == count($words) - 1) {
$lines[] = $current_line;
$line_widths[] = $line_width;
}
$last_width = $line_width;
$first_word = false;
}
if ($current_line) {
$current_line = $item;
}
}
// vertical align
if ($valign == self::ALIGN_CENTER) {
$top_offset = ($max_height - $largest_line_height * count($lines)) / 2;
} elseif ($valign == self::ALIGN_BOTTOM) {
$top_offset = $max_height - $largest_line_height * count($lines);
}
$top += $largest_line_height + $top_offset;
$i = 0;
fb($lines);
fb($line_widths);
foreach ($lines as $line) {
// horizontal align
if ($align == self::ALIGN_CENTER) {
$left_offset = ($max_width - $line_widths[$i]) / 2;
} elseif ($align == self::ALIGN_RIGHT) {
$left_offset = ($max_width - $line_widths[$i]);
}
// echo $font, "\n";
imagettftext($image, $size, $angle, $left + $left_offset, $top + ($largest_line_height * $i), $color, $font, $line);
$i++;
}
return $largest_line_height * count($lines);
}
function imagettftextSp($image, $size, $angle, $x, $y, $color, $font, $text, $spacing = 0)
{
if ($spacing == 0)
{
imagettftext($image, $size, $angle, $x, $y, $color, $font, $text);
}
else
{
$temp_x = $x;
for ($i = 0; $i < mb_strlen($text); $i++)
{
$bbox = imagettftext($image, $size, $angle, $temp_x, $y, $color, $font, $text[$i]);
$temp_x += $spacing + ($bbox[2] - $bbox[0]);
}
}
}
}
?>

438
core/tools/exceltable.php Normal file
View file

@ -0,0 +1,438 @@
<?php
class Excel_Number
{
public $value;
function __construct($value)
{
$this->value = $value;
}
function getString()
{
return $this->value;
}
}
class Excel_DateTime
{
public $value;
function __construct($value)
{
$this->value = intval($value);
}
function getString()
{
return date('Y-m-d\TH:i:s.u', $this->value);
}
}
/**
* Êëåòêà òàáëèöû
*/
class TableCell
{
public $style = false;
public $value;
public $merge = false;
function __construct ($value)
{
$this->value = $value;
}
}
/**
* Ðÿä òàáëèöû
*/
class TableRow
{
public $style = false;
public $cells = array();
public $height = false;
function setCell($y, $value)
{
$this->cells[$y] = new TableCell($value);
}
function setCellStyle($y, $name)
{
$this->cells[$y]->style = $name;
}
}
/**
* Òàáëèöà
*/
class ExcelTable
{
static $index;
private $name;
private $style;
protected $rows = array();
protected $splitVertical = false;
protected $splitHorizontal = false;
function __construct()
{
$this->name = "Page " . intval(self::$index ++);
}
/**
* Çàïèñàòü çíà÷åíèå â êëåòêó ñ çàäàííûìè êîîðäèíàòàìè
*/
function setCell($x, $y, $value)
{
assert(is_numeric($x) && $x > 0);
assert(is_numeric($y) && $y > 0);
if(! isset($this->rows[$x])) {
$this->rows[$x] = new TableRow();
}
$this->rows[$x]->setCell($y, $value);
}
/**
* Çàïîëíÿåò ðÿä íà÷èíàÿ ñ óêàçàííîãî ñòîëáöà çíà÷åíèÿìè èç ìàññèâà
*/
function setRow($row, $index, array $data)
{
assert(is_numeric($index) && $index > 0);
assert(is_numeric($row) && $row > 0);
reset($data);
for ($i = $index; $i < $index + count($data); $i++) {
$this->setCell($row, $i, current($data));
next($data);
}
}
/**
* Óñòàíàâëèâàåò âûñîòó ðÿäà
* @param $row integer Íîìåð ðÿäà
* @parma $value real Âûñîòà ðÿäà
*/
function setRowHeight ($row, $value)
{
assert(is_numeric($row) && $row > 0);
$this->rows[$row]->height = $value;
}
/**
* Óñòàíàâëèâàåò ñòèëü ðÿäà
* @param $row integer Íîìåð ðÿäà
* @parma $name string Èìÿ ñòèëÿ
*/
function setRowStyle ($row, $name)
{
assert(is_numeric($row) && $row > 0);
$this->rows[$row]->style = $name;
}
/**
* Îáüåäèíÿåò êëåòêè â ñòðîêå
* @param $row Íîìåð ðÿäà
* @param $cell Íîìåð ñòîëáöà
* @param $merge Êîëè÷åñòâî êëåòîê äëÿ îáüåäèíåíèÿ
*/
function setCellMerge ($row, $cell, $merge)
{
assert(is_numeric($row) && $row > 0);
assert(is_numeric($cell) && $cell > 0);
$this->rows[$row]->cells[$cell]->merge = $merge;
}
/**
* Óñòàíàâëèâàåò ñòèëü äëÿ êëåòîê ðÿäà
* @param $row integer Íîìåð ðÿäà
* @param $y integer Íîìåð ñòîëáöà
* @parma $name string Èìÿ ñòèëÿ
*/
function setCellStyle ($row, $y, $name)
{
if (isset($this->rows[$row]))
$this->rows[$row]->setCellStyle($y, $name);
}
/**
* Äîáàâëÿåò ñòðîêó ê òàáëèöå
*/
function addRow($index = 1, array $data = array(""))
{
assert(is_numeric($index) && $index > 0);
$offset = $this->getRows() + 1;
$this->setRow($offset, $index, $data);
return $offset;
}
/**
* Êîëè÷åñòâî ñòðîê â òàáëèöå
*
* @return int
*/
function getRows()
{
return max(array_keys($this->rows));
}
/**
* Êîëè÷åñòâî ñòîëáöîâ â ñòðîêå
*
* @return int
*/
function getRowCells($row)
{
return max(array_keys($row->cells));
}
/**
* Ðàçäåëÿåò òàáëèöó íà äâå ÷àñòè ïî âåðòèêàëè
* @param $n integer Êîëè÷åñòâî ñòîëáöîâ ñëåâà
*/
function splitVertical($n)
{
$this->splitVertical = $n;
}
/**
* Ðàçäåëÿåò òàáëèöó íà äâå ÷àñòè ïî ãîðèçîíòàëè
* @param $n integer Êîëè÷åñòâî ñòîëáöîâ ñâåðõó
*/
function splitHorizontal($n)
{
$this->splitHorizontal = $n;
}
/**
* Êîëè÷åñòâî ñòîëáöîâ â òàáëèöå
*
* @return int
*/
function getColumns()
{
return max(array_map(array($this, 'getRowCells'), $this->rows));
}
function encode($s)
{
return iconv("WINDOWS-1251", "UTF-8", $s);
}
/**
* Ãåíåðàöèÿ êëåòêè òàáëèöû (Ïåðåðàáîòàòü)
*/
function createCell ($ncell, XMLWriter $doc, $j, $value, $setIndex) {
$doc->startElement("Cell");
if ($ncell->style) {
$doc->writeAttribute('ss:StyleID', $ncell->style);
}
if ($ncell->merge) {
$doc->writeAttribute('ss:MergeAcross', $ncell->merge);
}
if ($setIndex) {
$doc->writeAttribute('ss:Index', $j);
}
$doc->startElement("Data");
if ($value instanceof Excel_DateTime) {
$doc->writeAttribute('ss:Type', "DateTime");
$doc->text($value->getString());
} else if ($value instanceof Excel_Number) {
$doc->writeAttribute('ss:Type', "Number");
$doc->text($value->getString());
} else {
if (is_string($value)) {
$doc->writeAttribute('ss:Type', "String");
} else {
$doc->writeAttribute('ss:Type', "Number");
}
$doc->writeCData($this->encode($value));
}
$doc->endElement();
$doc->endElement();
}
/**
* Ãåíåðàöèÿ òàáëèöû
*/
public function createTable (XMLWriter $doc) {
$doc->startElement('Worksheet');
$doc->writeAttribute('ss:Name', $this->name);
$columns = $this->getColumns();
$rows = $this->getRows();
$doc->startElement('Table');
$doc->writeAttribute('ss:ExpandedColumnCount', $columns);
$doc->writeAttribute('ss:ExpandedRowCount', $rows);
// Ïåðåïèñàòü öûêë !!!!!!!
for ($i = 1; $i <= $rows; $i++) {
$doc->startElement('Row');
if (isset($this->rows[$i])) {
if ($this->rows[$i]->style) {
$doc->writeAttribute('ss:StyleID', $this->rows[$i]->style);
}
if ($this->rows[$i]->height) {
$doc->writeAttribute('ss:Height', $this->rows[$i]->height);
}
$nrow = $this->rows[$i];
// Ôëàã èíäèêàòîð ïîäñòàíîâêè íîìåðà ñòîëáöà
$setIndex = false;
for ($j = 1; $j <= $columns; $j++) {
$value = null;
if (isset($nrow->cells[$j])) {
$value = $nrow->cells[$j]->value;
}
if (!empty($value)) {
$this->createCell($nrow->cells[$j], $doc, $j, $value, $setIndex);
$setIndex = false;
} else {
$setIndex = true;
}
}
}
$doc->endElement();
}
$doc->endElement();
$this->splitPane ($doc);
$doc->endElement();
}
protected function splitPane (XMLWriter $doc) {
$doc->startElement('WorksheetOptions');
$doc->writeAttribute('xmlns', 'urn:schemas-microsoft-com:office:excel');
$doc->writeElement('FrozenNoSplit');
if ($this->splitVertical) {
$doc->writeElement('SplitVertical', $this->splitVertical);
$doc->writeElement('LeftColumnRightPane', $this->splitVertical);
}
if ($this->splitHorizontal) {
$doc->writeElement('SplitHorizontal', $this->splitHorizontal);
$doc->writeElement('TopRowBottomPane', $this->splitHorizontal);
}
if ($this->splitHorizontal && $this->splitVertical) {
$doc->writeElement('ActivePane', 0);
} else if($this->splitHorizontal) {
$doc->writeElement('ActivePane', 2);
}
$doc->endElement();
}
}
/**
* Äîêóìåíò
*/
class ExcelDocument {
static $ns = "urn:schemas-microsoft-com:office:spreadsheet";
private $table = array ();
protected $styles = array();
function addTable($table) {
$this->table [] = $table;
}
/**
* Äîáàâëåíèå ñòèëÿ ê äîêóìåíòó
* @param $name string Èìÿ ñòèëÿ
* @param $values array Ïàðàìåòðû ñòèëÿ
* @param $type Òèï ñòèëÿ
*/
function setStyle ($name, array $values, $type = 'Interior')
{
if(!isset($this->styles[$name])) {
$this->styles[$name] = array();
}
$this->styles[$name][$type] = $values;
}
/**
* Ãåíåðàöèÿ ñòèëåé
*/
private function createStyles (XMLWriter $doc) {
$doc->startElement('Styles');
foreach ($this->styles as $name => $sn) {
$doc->startElement('Style');
$doc->writeAttribute('ss:ID', $name);
foreach ($sn as $type => $s) {
// Ñòèëü Borders - ñîñòàâíîé
if ($type == 'Borders') {
$doc->startElement('Borders');
foreach ($s as $border) {
$doc->startElement('Border');
foreach ($border as $key => $value) {
$doc->writeAttribute('ss:' . $key, $value);
}
$doc->endElement();
}
$doc->endElement();
} else {
$doc->startElement($type);
foreach ($s as $key => $value) {
$doc->writeAttribute('ss:' . $key, $value);
}
$doc->endElement();
}
}
$doc->endElement();
}
$doc->endElement();
}
/**
* Ïðåîáðàçóåò ïåðåâîäû ñòðîêè â ñïåö ñèìâîëû
*/
function clean ($s) {
assert(is_string($s));
return strtr($s, array ("\n" => '&#10;'));
}
/**
* Ñîõðàíÿåò òàáëèöó â ôîðìàòå Office 2003 XML
* http://en.wikipedia.org/wiki/Microsoft_Office_XML_formats
*/
function save($filename)
{
$doc = new xmlWriter();
$doc->openURI($filename);
$doc->setIndent(false);
$doc->startDocument('1.0','windows-1251');
$doc->startElement('Workbook');
$doc->writeAttribute('xmlns', self::$ns);
$doc->writeAttribute('xmlns:ss', self::$ns);
$this->createStyles($doc);
foreach ($this->table as $table) {
if ($table instanceof ExcelTable) {
$table->createTable($doc);
} else {
$table_data = call_user_func($table);
$table_data->createTable($doc);
unset($table_data);
}
}
$doc->endElement();
}
}
?>

40
core/tools/image.php Normal file
View file

@ -0,0 +1,40 @@
<?php
class Core_Tools_Image
{
static function load($uri)
{
$e = strtolower(pathinfo($uri, PATHINFO_EXTENSION));
switch ($e) {
case 'png': return imagecreatefrompng($uri);
case 'jpeg': case 'jpg': return imagecreatefromjpeg($uri);
case 'gif': return imagecreatefromgif($uri);
}
}
static function fit($image, $prewidth, $preheight, $force = true)
{
$width = imagesx($image);
$height = imagesy($image);
$percent = min($prewidth / $width, $preheight / $height);
if ($percent > 1 && !$force) $percent = 1;
$new_width = $width * $percent;
$new_height = $height * $percent;
$image_p = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
return $image_p;
}
static function save($image, $uri)
{
$e = strtolower(pathinfo($uri, PATHINFO_EXTENSION));
switch ($e) {
case 'jpg': imagejpeg($image, $uri, 100); break;
case 'png': imagepng($image, $uri); break;
case 'gif': imagegif($image, $uri); break;
}
}
}

33
core/tools/password.php Normal file
View file

@ -0,0 +1,33 @@
<?php
function generatePassword($length = 9, $strength = 0) {
$vowels = 'aeuy';
$consonants = 'bdghjmnpqrstvz';
if ($strength & 1) {
$consonants .= 'BDGHJLMNPQRSTVWXZ';
}
if ($strength & 2) {
$vowels .= "AEUY";
}
if ($strength & 4) {
$consonants .= '23456789';
}
if ($strength & 8) {
$consonants .= '@#$%';
}
$password = '';
$alt = time() % 2;
for ($i = 0; $i < $length; $i++) {
if ($alt == 1) {
$password .= $consonants[(rand() % strlen($consonants))];
$alt = 0;
} else {
$password .= $vowels[(rand() % strlen($vowels))];
$alt = 1;
}
}
return $password;
}
?>

37
core/tools/string.php Normal file
View file

@ -0,0 +1,37 @@
<?php
// from creole
function strToArray($str)
{
$str = substr($str, 1, -1); // remove { }
$res = array();
$subarr = array();
$in_subarr = 0;
$toks = explode(',', $str);
foreach($toks as $tok) {
if ($in_subarr > 0) { // already in sub-array?
$subarr[$in_subarr][] = $tok;
if ('}' === substr($tok, -1, 1)) { // check to see if we just added last component
$res[] = $this->strToArray(implode(',', $subarr[$in_subarr]));
$in_subarr--;
}
} elseif ($tok{0} === '{') { // we're inside a new sub-array
if ('}' !== substr($tok, -1, 1)) {
$in_subarr++;
// if sub-array has more than one element
$subarr[$in_subarr] = array();
$subarr[$in_subarr][] = $tok;
} else {
$res[] = $this->strToArray($tok);
}
} else { // not sub-array
$val = trim($tok, '"'); // remove " (surrounding strings)
// perform type castng here?
$res[] = $val;
}
}
return $res;
}

94
core/tools/tableview.php Normal file
View file

@ -0,0 +1,94 @@
<?php
class TableExcelView {
private $list = array();
private $data = array();
function setColumns(array $list) {
$this->list = $list;
}
function makeTable() {
$xls = new ExcelTable();
$xls->setRow(1, 1, array_keys($this->list));
foreach($this->data as $n => $item) {
$result = array();
foreach($this->list as $key => $c) {
if (is_callable($c)) {
$result [] = call_user_func($c, $item, $n);
} else {
if (is_numeric($item[$c])) {
$result [] = new Excel_Number($item[$c]);
} else {
$result [] = $item[$c];
}
}
}
$xls->addRow(1, $result);
}
return $xls;
}
function writeTable($data, $file) {
$this->data = $data;
$xls = new ExcelDocument();
$xls->addTable(array($this, 'makeTable'));
$xls->save($file);
}
}
class TableHTMLView {
private $list = array();
private $stack = array();
private $result = array();
function writeElement($name, $content) {
echo "<".$name.">";
echo $content;
echo "</".$name.">";
}
function startElement($name) {
array_push($this->stack, $name);
echo "<".$name.">";
}
function endElement() {
$name = array_pop($this->stack);
echo "</".$name.">";
}
function setColumns(array $list) {
$this->list = $list;
}
function writeTable($data) {
$this->startElement('table');
$this->startElement('thead');
$this->startElement('tr');
foreach($this->list as $key => $c) {
$this->writeElement('th', $key);
}
$this->endElement();
$this->endElement();
$this->startElement('tbody');
foreach($data as $n => $item) {
$this->startElement('tr');
foreach($this->list as $key => $c) {
if (is_callable($c)) {
$this->writeElement('td', call_user_func($c, $item, $n));
} else {
$this->writeElement('td', $item[$c]);
}
}
$this->endElement();
}
$this->endElement();
$this->endElement();
}
}

View file

@ -0,0 +1,207 @@
<?php
require_once 'core/tools/drawing.php';
/**
* Ôîðìàò äëÿ êîìïîçèöèè èçîáðàæåíèé
*/
class TemplateImage
{
static $listfiles = array('jpg' => 'jpeg', 'gif' => 'gif', 'png' => 'png', 'bmp' => 'wbmp');
static $listfonts = array(
'georgia' => 'georgia.ttf',
'georgiabd' => 'georgiab.ttf',
'georgiaz' => 'georgiaz.ttf',
'times' => 'times.ttf',
'timesbd' => 'timesbd.ttf',
'arial' => 'arial.ttf',
'arialbd' => 'arialbd.ttf',
'tahoma' => 'tahoma.ttf',
'calibri' => 'calibri.ttf',
'calibribd' => 'calibrib.ttf',
'calibrii' => 'calibrii.ttf',
'' => 'arial.ttf',
'dejavu' => 'DejaVuCondensedSerif.ttf',
'dejavubd' => 'DejaVuCondensedSerifBold.ttf',
'dejavuz' =>'DejaVuCondensedSerifBoldItalic.ttf',
'dejavui' => 'DejaVuCondensedSerifItalic.ttf',
'miriad' => 'MyriadPro-Cond.ttf',
'miriadbd' => 'MyriadPro-BoldCond.ttf'
);
protected $src;
protected $context = array();
protected $data = array();
protected $base = "c:\\windows\\fonts\\";
protected $image;
protected $prepare = true;
public $debug = false;
function __construct ($template = false)
{
// assert(is_string($src));
if($template) {
$this->data = $template;
}
}
/**
* Ïóòü ê èçîáðàæåíèþ
*/
function resourcePath($path)
{
assert(is_string($path));
$this->resource = $path;
}
/**
* Ïóòü ó øðèôòàì
*/
function fontPath($path)
{
assert(is_string($path));
$this->base = $path;
}
function set($name, $value)
{
assert(is_string($name));
$this->context['['.$name.']'] = $this->encode($value);
}
function setImage($name)
{
$this->filename = $name;
$this->image = $this->imagefromfile($name);
}
function setEmptyImage($width, $height)
{
$this->image = imagecreatetruecolor($width, $height);
}
/**
* Ñîçäàåò èçîáðàæåíèå èç ôàéëà
*/
function imagefromfile($file)
{
assert(is_string($file));
$suffix = pathinfo($file, PATHINFO_EXTENSION);
if (array_key_exists($suffix, self::$listfiles)) {
return call_user_func('imagecreatefrom' . self::$listfiles[$suffix], $file);
}
return null;
}
function getFontFile($name)
{
assert(is_string($name));
if(array_key_exists(strtolower($name), self::$listfonts)) {
return $this->base . self::$listfonts[$name];
}
return $this->base . 'arial.ttf';
}
function fontSuffix($style)
{
if($style[0] && $style[1]) return "z";
if($style[0]) return "bd";
if($style[1]) return "i";
return "";
}
function imageText($text, $value)
{
assert(is_string($text));
$text = strtr($text, $this->context);
$size = $value->fontSize;
fb('font-style');
fb($value->fontStyle);
$fontfile = $this->getFontFile($value->fontFamily . $this->fontSuffix($value->fontStyle));
$color = intval(substr($value->color, 1), 16);
if ($value->align[0]) {
$align = Drawing::ALIGN_LEFT;
} elseif ($value->align[2]) {
$align = Drawing::ALIGN_RIGHT;
} else {
$align = Drawing::ALIGN_CENTER;
}
if ($value->valign[0]) {
$valign = Drawing::ALIGN_TOP;
} elseif ($value->valign[1]) {
$valign = Drawing::ALIGN_CENTER;
} else {
$valign = Drawing::ALIGN_BOTTOM;
}
Drawing::imagettftextbox($this->image, $size, 0, $value->left, $value->top, $color, $fontfile, $text,
$value->width, $value->height,
$align, $valign);
}
/**
* Ïåðåêîäèðîâêà òåêñòà
*/
function encode($text)
{
assert(is_string($text));
return iconv("WINDOWS-1251", "UTF-8", $text);
}
function setSize($new_width, $new_height)
{
$width = imagesx($this->image);
$height = imagesy($this->image);
if($new_height == false) {
$new_height = ceil($height * $new_width / $width);
}
// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($image_p, $this->image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
// imagecopyresized($image_p, $this->image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
$this->image = $image_p;
}
function prepare() {
if($this->prepare) {
$this->prepare = false;
foreach ($this->data as $value) {
$this->imageText($value->text, $value); // break;
}
}
}
/**
* Ãåíåðèðóåò èçîáðàæåíèå èç øàáëîíà
*/
function render($file = null)
{
assert(is_string($file) || is_null($file));
$this->prepare();
if ($file == null) {
ob_start();
imagejpeg($this->image, $file, 100);
$result = ob_get_contents();
ob_clean();
return $result;
} else {
return imagejpeg($this->image, $file, 100);
}
}
}
?>

14
core/tools/translit.php Normal file
View file

@ -0,0 +1,14 @@
<?php
function translit($st) {
$st = strtr($st,"àáâãäå¸çèéêëìíîïðñòóôõúûý !¹", "abvgdeeziyklmnoprstufh_ie__#");
$st = strtr($st,"ÀÁÂÃÄŨÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÚÛÝ", "ABVGDEEZIYKLMNOPRSTUFH_IE");
$st = strtr($st, array(
"æ"=>"zh", "ö"=>"ts", "÷"=>"ch", "ø"=>"sh",
"ù"=>"shch","ü"=>"", "þ"=>"yu", "ÿ"=>"ya",
"Æ"=>"ZH", "Ö"=>"TS", "×"=>"CH", "Ø"=>"SH",
"Ù"=>"SHCH","Ü"=>"", "Þ"=>"YU", "ß"=>"YA",
"¿"=>"i", "¯"=>"Yi", "º"=>"ie", "ª"=>"Ye"
));
return $st;
}

135
core/tree/database.php Normal file
View file

@ -0,0 +1,135 @@
<?php
//****************************************************************************
// phpDatabase 2.1
//****************************************************************************
// Author: Maxim Poltarak <maxx at e dash taller dot net>
// Category: Databases
//****************************************************************************
// The lib is FREEWARE. This means you may use it anywhere you want, you may
// do anything with it. The Author mentioned above is NOT responsible for any
// consequences of using this library.
// If you don't agree with this, you MAY NOT use the lib!
//****************************************************************************
// All improvings, feature requests, bug reports, etc. are gladly accepted.
//****************************************************************************
// Note: For best viewing of the code Tab size 4 is recommended
//****************************************************************************
class CDatabase
{
var $link;
var $db;
var $host, $user, $pass;
function CDatabase($db, $host = "localhost", $user = "", $pass = "")
{
$this->db = $db;
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$str = "host={$host} port=5432 dbname={$db} user={$user} password={$pass}";
$this->link = pg_connect($str);
}
function query($sql)
{
if (!$this->link) return 0;
return pg_query($this->link, $sql);
}
function affected_rows()
{
return pg_affected_rows($this->link);
}
function num_rows($q)
{
return pg_num_rows($q);
}
function fetch_array($q) // fetchAll
{
return pg_fetch_array($q, NULL);
}
function fetch_object($q) // fetchObject
{
return pg_fetch_object($q);
}
/* function data_seek($q, $n) {
return pg_data_seek($q, $n);
}
*/
function free_result($q)
{
return pg_free_result($q);
}
function insert_id($seq)
{
$query = "SELECT currval('$seq')";
$res = $this->query($query);
$row = pg_fetch_array($res, NULL, PGSQL_ASSOC);
pg_free_result($res);
return ($row) ? $row['currval'] : 0;
}
function error()
{
return pg_last_error($this->link);
}
function error_die($msg = '')
{
die(((empty($msg)) ? '' : $msg . ': ') . $this->error());
}
function sql2var($sql)
{
if ((empty($sql)) || (!($query = $this->query($sql)))) return false;
if ($this->num_rows($query) < 1) return false;
return $this->result2var($query);
}
function result2var($q)
{
if (!($Data = $this->fetch_array($q))) return false;
$this->free_result($q);
foreach($Data as $k => $v) $GLOBALS[$k] = $v;
return true;
}
/*function sql2array($sql, $keyField = '')
{
if ((empty($sql)) || (!($query = $this->query($sql)))) return false;
if ($this->num_rows($query) < 1) return false;
return $this->result2array($query, $keyField);
}*/
function result2array($q, $keyField = '')
{
$Result = array();
while ($Data = $this->fetch_array($q))
if (empty($keyField)) $Result[] = $Data;
else $Result[$Data[$keyField]] = $Data;
$this->free_result($q);
return $Result;
}
/*function list_tables()
{
return mysql_list_tables($this->db, $this->link);
}
function list_fields($table_name)
{
return mysql_list_fields($this->db, $table_name, $this->link);
}*/
};

636
core/tree/dbtree.php Normal file
View file

@ -0,0 +1,636 @@
<?php
//****************************************************************************
// phpDBTree 1.4
//****************************************************************************
// Author: Maxim Poltarak <maxx at e dash taller dot net>
// WWW: http://dev.e-taller.net/dbtree/
// Category: Databases
// Description: PHP class implementing a Nested Sets approach to storing
// tree-like structures in database tables. This technique was
// introduced by Joe Celko <http://www.celko.com/> and has some
// advantages over a widely used method called Adjacency Matrix.
//****************************************************************************
// The lib is FREEWARE. That means you may use it anywhere you want, you may
// do anything with it. The Author mentioned above is NOT responsible for any
// consequences of using this library.
// If you don't agree with this, you are NOT ALLOWED to use the lib!
//****************************************************************************
// You're welcome to send me all improvings, feature requests, bug reports...
//****************************************************************************
// SAMPLE DB TABLE STRUCTURE:
//
// CREATE TABLE categories (
// cat_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
// cat_left INT UNSIGNED NOT NULL,
// cat_right INT UNSIGNED NOT NULL,
// cat_level INT UNSIGNED NOT NULL,
// PRIMARY KEY(cat_id),
// KEY(cat_left, cat_right, cat_level)
// );
//
// This is believed to be the optimal Nested Sets use case. Use `one-to-one`
// relations on `cat_id` field between this `structure` table and
// another `data` table in your database.
//
// Don't forget to make a single call to clear()
// to set up the Root node in an empty table.
//
//****************************************************************************
// NOTE: Although you may use this library to retrieve data from the table,
// it is recommended to write your own queries for doing that.
// The main purpose of the library is to provide a simpler way to
// create, update and delete records. Not to SELECT them.
//****************************************************************************
//
// IMPORTANT! DO NOT create either UNIQUE or PRIMARY keys on the set of
// fields (`cat_left`, `cat_right` and `cat_level`)!
// Unique keys will destroy the Nested Sets structure!
//
//****************************************************************************
// CHANGELOG:
// 16-Apr-2003 -=- 1.1
// - Added moveAll() method
// - Added fourth parameter to the constructor
// - Renamed getElementInfo() to getNodeInfo() /keeping BC/
// - Added "Sample Table Structure" comment
// - Now it trigger_error()'s in case of any serious error, because if not you
// will lose the Nested Sets structure in your table
// 19-Feb-2004 -=- 1.2
// - Fixed a bug in moveAll() method?
// Thanks to Maxim Matyukhin for the patch.
// 13-Jul-2004 -=- 1.3
// - Changed all die()'s for a more standard trigger_error()
// Thanks to Dmitry Romakhin for pointing out an issue with
// incorrect error message call.
// 09-Nov-2004 -=- 1.4
// - Added insertNear() method.
// Thanks to Michael Krenz who sent its implementation.
// - Removed IGNORE keyword from UPDATE clauses in insert() methods.
// It was dumb to have it there all the time. Sorry. Anyway, you had
// to follow the important note mencioned above. If you hadn't, you're
// in problem.
//
//****************************************************************************
// Note: For best viewing of the code Tab size 4 is recommended
//****************************************************************************
function _case($c, $then, $else) {
return " (CASE WHEN $c THEN $then ELSE $else END) ";
}
function _between($a, $x, $y) {
return " " . $a . " BETWEEN " . $x . " AND " . $y;
}
function _inside($a, $x, $y) {
return " " . $a . " > " . $x . " AND " . $a . " < " . $y;
}
class CDBTree
{
var $db; // CDatabase class to plug to
var $table; // Table with Nested Sets implemented
var $id; // Name of the ID-auto_increment-field in the table.
// These 3 variables are names of fields which are needed to implement
// Nested Sets. All 3 fields should exist in your table!
// However, you may want to change their names here to avoid name collisions.
var $left = 'cat_left';
var $right = 'cat_right';
var $level = 'cat_level';
var $qryParams = '';
var $qryFields = '';
var $qryTables = '';
var $qryWhere = '';
var $qryGroupBy = '';
var $qryHaving = '';
var $qryOrderBy = '';
var $qryLimit = '';
var $sqlNeedReset = true;
var $sql; // Last SQL query
//************************************************************************
// Constructor
// $DB : CDatabase class instance to link to
// $tableName : table in database where to implement nested sets
// $itemId : name of the field which will uniquely identify every record
// $fieldNames : optional configuration array to set field names. Example:
// array(
// 'left' => 'cat_left',
// 'right' => 'cat_right',
// 'level' => 'cat_level'
// )
function CDBTree(&$DB, $tableName, $itemId, $seq, $fieldNames = array())
{
if (empty($tableName)) trigger_error("phpDbTree: Unknown table", E_USER_ERROR);
if (empty($itemId)) trigger_error("phpDbTree: Unknown ID column", E_USER_ERROR);
$this->seq = $seq;
$this->db = $DB;
$this->table = $tableName;
$this->id = $itemId;
if (is_array($fieldNames) && sizeof($fieldNames))
foreach($fieldNames as $k => $v) $this->$k = $v;
}
//************************************************************************
// Returns a Left and Right IDs and Level of an element or false on error
// $ID : an ID of the element
function getElementInfo($ID)
{
return $this->getNodeInfo($ID);
}
function getNodeInfo($ID)
{
$this->sql = 'SELECT ' . $this->left . ',' . $this->right . ',' . $this->level . ' FROM ' . $this->table . ' WHERE ' . $this->id . '=\'' . $ID . '\'';
// print_r($this->sql);
if (($query = $this->db->query($this->sql)) && ($this->db->num_rows($query) == 1) && ($Data = $this->db->fetch_array($query))) return array(
(int)$Data[$this->left],
(int)$Data[$this->right],
(int)$Data[$this->level]
);
else trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR); // throw new Exception();
}
//************************************************************************
// Clears table and creates 'root' node
// $data : optional argument with data for the root node
function clear($data = array())
{
// clearing table
if ((!$this->db->query('TRUNCATE ' . $this->table)) && (!$this->db->query('DELETE FROM ' . $this->table))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// preparing data to be inserted
if (sizeof($data)) {
$fld_names = implode(',', array_keys($data)) . ',';
if (sizeof($data)) $fld_values = '\'' . implode('\',\'', array_values($data)) . '\',';
}
$fld_names.= $this->left . ',' . $this->right . ',' . $this->level;
$fld_values.= '1,2,0';
// inserting new record
$this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')';
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
return $this->db->insert_id($this->seq);
}
//************************************************************************
// Updates a record
// $ID : element ID
// $data : array with data to update: array(<field_name> => <fields_value>)
function update($ID, $data)
{
$sql_set = '';
foreach($data as $k => $v) $sql_set.= ',' . $k . '=\'' . addslashes($v) . '\'';
return $this->db->query('UPDATE ' . $this->table . ' SET ' . substr($sql_set, 1) . ' WHERE ' . $this->id . '=\'' . $ID . '\'');
}
//************************************************************************
// Inserts a record into the table with nested sets
// $ID : an ID of the parent element
// $data : array with data to be inserted: array(<field_name> => <field_value>)
// Returns : true on success, or false on error
function insert($ID, $data)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// preparing data to be inserted
if (sizeof($data)) {
$fld_names = implode(',', array_keys($data)) . ',';
$fld_values = '\'' . implode('\',\'', array_values($data)) . '\',';
}
$fld_names.= $this->left . ',' . $this->right . ',' . $this->level;
$fld_values.= ($rightId) . ',' . ($rightId+1) . ',' . ($level+1);
// creating a place for the record being inserted
if ($ID) {
$this->sql = 'UPDATE ' . $this->table . ' SET ' . $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '+2', $this->left) . ',' . $this->right . '=' . _case($this->right . '>=' . $rightId, $this->right . '+2', $this->right) . 'WHERE ' . $this->right . '>=' . $rightId;
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
}
// inserting new record
$this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')';
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
return $this->db->insert_id($this->seq);
}
//************************************************************************
// Inserts a record into the table with nested sets
// $ID : ID of the element after which (i.e. at the same level) the new element
// is to be inserted
// $data : array with data to be inserted: array(<field_name> => <field_value>)
// Returns : true on success, or false on error
function insertNear($ID, $data)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// preparing data to be inserted
if (sizeof($data)) {
$fld_names = implode(',', array_keys($data)) . ',';
$fld_values = '\'' . implode('\',\'', array_values($data)) . '\',';
}
$fld_names.= $this->left . ',' . $this->right . ',' . $this->level;
$fld_values.= ($rightId+1) . ',' . ($rightId+2) . ',' . ($level);
// creating a place for the record being inserted
if ($ID) {
$this->sql = 'UPDATE ' . $this->table . ' SET ' . $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '+2', $this->left) . $this->right . '=' . _case($this->right . '>' . $rightId, $this->right . '+2', $this->right) . 'WHERE ' . $this->right . '>' . $rightId;
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error:" . $this->db->error() , E_USER_ERROR);
}
// inserting new record
$this->sql = 'INSERT INTO ' . $this->table . '(' . $fld_names . ') VALUES(' . $fld_values . ')';
if (!($this->db->query($this->sql))) trigger_error("phpDbTree error:" . $this->db->error() , E_USER_ERROR);
return $this->db->insert_id($this->seq);
}
//************************************************************************
// Assigns a node with all its children to another parent
// $ID : node ID
// $newParentID : ID of new parent node
// Returns : false on error
function moveAll($ID, $newParentId)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
if (!(list($leftIdP, $rightIdP, $levelP) = $this->getNodeInfo($newParentId))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
if ($ID == $newParentId || $leftId == $leftIdP || ($leftIdP >= $leftId && $leftIdP <= $rightId)) return false;
// whether it is being moved upwards along the path
if ($leftIdP < $leftId && $rightIdP > $rightId && $levelP < $level-1) {
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . ","
. $this->right . '=' . _case($this->right . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->right . '-' . ($rightId-$leftId+1)
, _case($this->left . ' BETWEEN ' . ($leftId) . ' AND ' . ($rightId) , $this->right . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->right)) . ","
. $this->left . '=' . _case($this->left . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->left . '-' . ($rightId-$leftId+1) , _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . ($rightId) , $this->left . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->left)) . 'WHERE ' . $this->left . ' BETWEEN ' . ($leftIdP+1) . ' AND ' . ($rightIdP-1);
} elseif ($leftIdP < $leftId) {
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . ","
. $this->left . '=' . _case($this->left . ' BETWEEN ' . $rightIdP . ' AND ' . ($leftId-1) , $this->left . '+' . ($rightId-$leftId+1)
, _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '-' . ($leftId-$rightIdP) , $this->left)) . ","
. $this->right . '=' . _case($this->right . ' BETWEEN ' . $rightIdP . ' AND ' . $leftId, $this->right . '+' . ($rightId-$leftId+1) , _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '-' . ($leftId-$rightIdP) , $this->right)) . 'WHERE ' . $this->left . ' BETWEEN ' . $leftIdP . ' AND ' . $rightId
// !!! added this line (Maxim Matyukhin)
. ' OR ' . $this->right . ' BETWEEN ' . $leftIdP . ' AND ' . $rightId;
} else {
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level) . ","
. $this->left . '=' . _case($this->left . ' BETWEEN ' . $rightId . ' AND ' . $rightIdP, $this->left . '-' . ($rightId-$leftId+1)
, _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '+' . ($rightIdP-1-$rightId), $this->left)) . ", "
. $this->right . '=' . _case($this->right . ' BETWEEN ' . ($rightId+1) . ' AND ' . ($rightIdP-1) , $this->right . '-' . ($rightId-$leftId+1) , _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '+' . ($rightIdP-1-$rightId) , $this->right)) . 'WHERE ' . $this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightIdP
// !!! added this line (Maxim Matyukhin)
. ' OR ' . $this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightIdP;
}
return $this->db->query($this->sql) or trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
}
// Ïåðåìåùåíèå âñåõ äåòåé âåòêè â äðóãóþ âåòêó
function moveChildren($ID, $newParentId)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
if (!(list($leftIdP, $rightIdP, $levelP) = $this->getNodeInfo($newParentId))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
if ($ID == $newParentId || $leftId == $leftIdP || ($leftIdP >= $leftId && $leftIdP <= $rightId)) return false;
// whether it is being moved upwards along the path
if ($leftIdP < $leftId && $rightIdP > $rightId && $levelP < $level-1) {
// _update($this->table, array(), )
$this->sql = 'UPDATE ' . $this->table . ' SET '
// Ìåíÿåì óðîâåíü
. $this->level . '=' .
_case(_between($this->left, $leftId, $rightId),
$this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level)
// Ìåíÿåì ãðàíèöû
. $this->left . '=' .
_case(_beetween($this->left, $rightId+1, $rightIdP-1), $this->left . '-' . $rightId-$leftId+1 ,
_case(_between($this->left, $leftId, $rightId), $this->left . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->left))
. $this->right . '=' .
_case(_between($this->right, $rightId+1, $rightIdP-1), $this->right . '-' . ($rightId-$leftId+1) ,
_case(_between($this->left, $leftId, $rightId), $this->right . '+' . ((($rightIdP-$rightId-$level+$levelP) /2) *2+$level-$levelP-1) , $this->right))
. 'WHERE ' . _between($this->left, ($leftIdP+1), ($rightIdP-1));
} elseif ($leftIdP < $leftId) {
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->level . '=' .
_case(_between($this->left, $leftId, $rightId),
$this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level)
. $this->left . '=' .
_case(_between($this->left, $rightIdP, $leftId-1), $this->left . '+' . ($rightId-$leftId+1),
_case(_between($this->left, $leftId, $rightId), $this->left . '-' . ($leftId-$rightIdP) , $this->left))
. $this->right . '=' .
_case(_between($this->right, $rightIdP, $leftId), $this->right . '+' . ($rightId-$leftId+1),
_case(_between($this->right, $leftId, $rightId), $this->right . '-' . ($leftId-$rightIdP) , $this->right))
. 'WHERE ' . _between($this->left, $leftIdP, $rightId)
// !!! added this line (Maxim Matyukhin)
. ' OR ' . _between($this->right, $leftIdP, $rightId);
} else {
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->level . '='
. _case(_between($this->left, $leftId, $rightId),
$this->level . sprintf('%+d', -($level-1) +$levelP) , $this->level)
. $this->left . '=' .
_case(_between($this->left, $rightId, $rightIdP), $this->left . '-' . ($rightId-$leftId+1),
_case(_between($this->left, $leftId, $rightId), $this->left . '+' . ($rightIdP-1-$rightId), $this->left))
. $this->right . '=' .
_case(_between($this->right, $rightId+1, $rightIdP-1), $this->right . '-' . ($rightId-$leftId+1),
_case(_between($this->right, $leftId, $rightId), $this->right . '+' . ($rightIdP-1-$rightId) , $this->right))
. 'WHERE ' . _between($this->left, $leftId, $rightIdP)
// !!! added this line (Maxim Matyukhin)
. ' OR ' . _between($this->right, $leftId, $rightIdP);
}
return $this->db->query($this->sql) or trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
}
//************************************************************************
// Deletes a record wihtout deleting its children
// $ID : an ID of the element to be deleted
// Returns : true on success, or false on error
function delete($ID)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// Deleting record
$this->sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->id . '=\'' . $ID . '\'';
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// Clearing blank spaces in a tree
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->left . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->left . '-1', $this->left) . ", "
. $this->right . '=' . _case($this->right . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->right . '-1', $this->right) . ", "
. $this->level . '=' . _case($this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId, $this->level . '-1', $this->level) . ", "
. $this->left . '=' . _case($this->left . '>' . $rightId, $this->left . '-2', $this->left) . ", "
. $this->right . '=' . _case($this->right . '>' . $rightId, $this->right . '-2', $this->right)
. ' WHERE ' . $this->right . '>' . $leftId;
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
return true;
}
//************************************************************************
// Deletes a record with all its children
// $ID : an ID of the element to be deleted
// Returns : true on success, or false on error
function deleteAll($ID)
{
if (!(list($leftId, $rightId, $level) = $this->getNodeInfo($ID))) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// Deleteing record(s)
$this->sql = 'DELETE FROM ' . $this->table . ' WHERE ' . $this->left . ' BETWEEN ' . $leftId . ' AND ' . $rightId;
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// Clearing blank spaces in a tree
$deltaId = ($rightId-$leftId) +1;
$this->sql = 'UPDATE ' . $this->table . ' SET '
. $this->left . '=' . _case($this->left . '>' . $leftId, $this->left . '-' . $deltaId, $this->left) . ", "
. $this->right . '=' . _case($this->right . '>' . $leftId, $this->right . '-' . $deltaId, $this->right)
. ' WHERE ' . $this->right . '>' . $rightId;
if (!$this->db->query($this->sql)) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
return true;
}
//************************************************************************
// Enumerates children of an element
// $ID : an ID of an element which children to be enumerated
// $start_level : relative level from which start to enumerate children
// $end_level : the last relative level at which enumerate children
// 1. If $end_level isn't given, only children of
// $start_level levels are enumerated
// 2. Level values should always be greater than zero.
// Level 1 means direct children of the element
// Returns : a result id for using with other DB functions
function enumChildrenAll($ID)
{
return $this->enumChildren($ID, 1, 0);
}
function enumChildren($ID, $start_level = 1, $end_level = 1)
{
if ($start_level < 0) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
// We could use sprintf() here, but it'd be too slow
$whereSql1 = ' AND ' . $this->table . '.' . $this->level;
$whereSql2 = '_' . $this->table . '.' . $this->level . '+';
if (!$end_level) $whereSql = $whereSql1 . '>=' . $whereSql2 . (int)$start_level;
else {
$whereSql = ($end_level <= $start_level) ? $whereSql1 . '=' . $whereSql2 . (int)$start_level : ' AND ' . $this->table . '.' . $this->level . ' BETWEEN _' . $this->table . '.' . $this->level . '+' . (int)$start_level . ' AND _' . $this->table . '.' . $this->level . '+' . (int)$end_level;
}
$this->sql = $this->sqlComposeSelect(array(
'', // Params
'', // Fields
$this->table . ' _' . $this->table . ', ' . $this->table, // Tables
'_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND ' . $this->table . '.' . $this->left . ' BETWEEN _' . $this->table . '.' . $this->left . ' AND _' . $this->table . '.' . $this->right . $whereSql
));
return $this->db->query($this->sql);
}
function enumChildrenArray($ID, $start_level = 1, $end_level = 1)
{
return $this->db->result2array($this->enumChildren($ID, $start_level, $end_level));
}
//************************************************************************
// Enumerates the PATH from an element to its top level parent
// $ID : an ID of an element
// $showRoot : whether to show root node in a path
// Returns : a result id for using with other DB functions
function enumPath($ID, $showRoot = false)
{
$this->sql = $this->sqlComposeSelect(array(
'', // Params
'', // Fields
$this->table . ' _' . $this->table . ', ' . $this->table, // Tables
'_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND _' . $this->table . '.' . $this->left . ' BETWEEN ' . $this->table . '.' . $this->left . ' AND ' . $this->table . '.' . $this->right . (($showRoot) ? '' : ' AND ' . $this->table . '.' . $this->level . '>0') , // Where
'', // GroupBy
'', // Having
$this->table . '.' . $this->left // OrderBy
));
return $this->db->query($this->sql);
}
function enumPathArray($ID, $showRoot = false)
{
return $this->db->result2array($this->enumPath($ID, $showRoot));
}
//************************************************************************
// Returns query result to fetch data of the element's parent
// $ID : an ID of an element which parent to be retrieved
// $level : Relative level of parent
// Returns : a result id for using with other DB functions
function getParent($ID, $level = 1)
{
if ($level < 1) trigger_error("phpDbTree error: " . $this->db->error() , E_USER_ERROR);
$this->sql = $this->sqlComposeSelect(array(
'', // Params
'', // Fields
$this->table . ' _' . $this->table . ', ' . $this->table, // Tables
'_' . $this->table . '.' . $this->id . '=\'' . $ID . '\'' . ' AND _' . $this->table . '.' . $this->left . ' BETWEEN ' . $this->table . '.' . $this->left . ' AND ' . $this->table . '.' . $this->right . ' AND ' . $this->table . '.' . $this->level . '=_' . $this->table . '.' . $this->level . '-' . (int)$level // Where
));
$result = $this->db->result2array($this->db->query($this->sql));
return (int)$result[0][$this->id];
}
//************************************************************************
function sqlReset()
{
$this->qryParams = '';
$this->qryFields = '';
$this->qryTables = '';
$this->qryWhere = '';
$this->qryGroupBy = '';
$this->qryHaving = '';
$this->qryOrderBy = '';
$this->qryLimit = '';
return true;
}
//************************************************************************
function sqlSetReset($resetMode)
{
$this->sqlNeedReset = ($resetMode) ? true : false;
}
//************************************************************************
function sqlParams($param = '')
{
return (empty($param)) ? $this->qryParams : $this->qryParams = $param;
}
function sqlFields($param = '')
{
return (empty($param)) ? $this->qryFields : $this->qryFields = $param;
}
function sqlSelect($param = '')
{
return $this->sqlFields($param);
}
function sqlTables($param = '')
{
return (empty($param)) ? $this->qryTables : $this->qryTables = $param;
}
function sqlFrom($param = '')
{
return $this->sqlTables($param);
}
function sqlWhere($param = '')
{
return (empty($param)) ? $this->qryWhere : $this->qryWhere = $param;
}
function sqlGroupBy($param = '')
{
return (empty($param)) ? $this->qryGroupBy : $this->qryGroupBy = $param;
}
function sqlHaving($param = '')
{
return (empty($param)) ? $this->qryHaving : $this->qryHaving = $param;
}
function sqlOrderBy($param = '')
{
return (empty($param)) ? $this->qryOrderBy : $this->qryOrderBy = $param;
}
function sqlLimit($param = '')
{
return (empty($param)) ? $this->qryLimit : $this->qryLimit = $param;
}
//************************************************************************
function sqlComposeSelect($arSql)
{
$joinTypes = array(
'join' => 1,
'cross' => 1,
'inner' => 1,
'straight' => 1,
'left' => 1,
'natural' => 1,
'right' => 1
);
$this->sql = 'SELECT ' . $arSql[0] . ' ';
if (!empty($this->qryParams)) $this->sql.= $this->sqlParams . ' ';
if (empty($arSql[1]) && empty($this->qryFields)) $this->sql.= $this->table . '.' . $this->id;
else {
if (!empty($arSql[1])) $this->sql.= $arSql[1];
if (!empty($this->qryFields)) $this->sql.= ((empty($arSql[1])) ? '' : ',') . $this->qryFields;
}
$this->sql.= ' FROM ';
// $tblAr = array(0 => 'join');
$isJoin = ($tblAr = explode(' ', trim($this->qryTables)))
&& /*($joinTypes[strtolower($tblAr[0]) ])*/ 1;
if (empty($arSql[2]) && empty($this->qryTables)) $this->sql.= $this->table;
else {
if (!empty($arSql[2])) $this->sql.= $arSql[2];
if (!empty($this->qryTables)) {
if (!empty($arSql[2])) $this->sql.= (($isJoin) ? ' ' : ',');
elseif ($isJoin) $this->sql.= $this->table . ' ';
$this->sql.= $this->qryTables;
}
}
if ((!empty($arSql[3])) || (!empty($this->qryWhere))) {
$this->sql.= ' WHERE ' . $arSql[3] . ' ';
if (!empty($this->qryWhere)) $this->sql.= (empty($arSql[3])) ? $this->qryWhere : 'AND(' . $this->qryWhere . ')';
}
if ((!empty($arSql[4])) || (!empty($this->qryGroupBy))) {
$this->sql.= ' GROUP BY ' . $arSql[4] . ' ';
if (!empty($this->qryGroupBy)) $this->sql.= (empty($arSql[4])) ? $this->qryGroupBy : ',' . $this->qryGroupBy;
}
if ((!empty($arSql[5])) || (!empty($this->qryHaving))) {
$this->sql.= ' HAVING ' . $arSql[5] . ' ';
if (!empty($this->qryHaving)) $this->sql.= (empty($arSql[5])) ? $this->qryHaving : 'AND(' . $this->qryHaving . ')';
}
if ((!empty($arSql[6])) || (!empty($this->qryOrderBy))) {
$this->sql.= ' ORDER BY ' . (isset($arSql[6]) ? $arSql[6] : '') . ' ';
if (!empty($this->qryOrderBy)) $this->sql.= (empty($arSql[6])) ? $this->qryOrderBy : ',' . $this->qryOrderBy;
}
if (!empty($arSql[7])) $this->sql.= ' LIMIT ' . $arSql[7];
elseif (!empty($this->qryLimit)) $this->sql.= ' LIMIT ' . $this->qryLimit;
if ($this->sqlNeedReset) $this->sqlReset();
return $this->sql;
}
//************************************************************************
}

79
core/tree/sort.php Normal file
View file

@ -0,0 +1,79 @@
<?php
/**
* Ñîðòèðîâêà äåðåâà â ïðåäñòàâëåíèè Nested Set
* Äëÿ äåðåâà êîòîðîå õðàíèòñÿ â áàçå äàííûõ èñïîëüçóÿ ïðåäñòàâëåíèå Nested Set íåò âîçìîæíîñòè îòñîðòèðîâàòü ýëåìåíòû äåðåâà ïî
* ïðîèçâîëüíîìó ïîëþ. Ïîýòîìó ïîñëå èçâëå÷åíèÿ äåðåâà èç áàçû äàííûõ îíî ïðåîáðàçóåòñÿ â îáû÷íîå ïðåäñòàâëåíèå ñîðòèðóåòñÿ è îáðàòíî
*
* Ïðèìåð:
* $sort = new NestedSetSort();
* $data = $sort->sortBy($data, 'name');
*/
class NestedSetSort {
private $data = array();
private $result = array();
private $sortBy = '';
public function __construct() {
}
// Ïðåîáðàçóåì Nested Set â äåðåâî è ñîðòèðóåì
private function listTree(array $tree, $offset, $level) {
$result = array();
for ($i = $offset; $i < sizeof($tree); $i++) {
$leaf = $tree[$i];
$clevel = $leaf['cat_level'];
if ($clevel == $level) {
$result [] = array($i);
} else if ($clevel > $level) {
list($subtree, $i) = $this->listTree($tree, $i, $clevel);
$i--;
$result[sizeof($result) - 1][1] = $subtree;
} else {
$this->sortList($result, $tree);
return array($result, $i);
}
}
$this->sortList($result, $tree);
return array($result, $i);
}
// Ñðàâíåíèå äâóõ ýëåìåíòîâ
private function compare($a, $b) {
$a1 = $this->data[$a[0]][$this->sortBy];
$b1 = $this->data[$b[0]][$this->sortBy];
return strcmp($a1, $b1);
}
// Ñîðòèðîâêà ñïèñêà
private function sortList(array &$list, $data) {
usort($list, array($this, 'compare'));
}
// Ñîçäàåò äåðåâî â âèäå ñïèñêà
private function reorder(array $tree) {
foreach($tree as $node) {
$this->result[] = $this->data[$node[0]];
if (isset($node[1])) {
$this->reorder($node[1]);
}
}
}
public function sortBy0(array $data, $sortBy)
{
$this->data = $data;
$this->sortBy = $sortBy;
$order = $this->listTree($data, 0, 0);
return $order[0];
}
// Ñîðòèðîâêà ïî çàäàííîìó ïîëþ
public function sortBy(array $data, $sortBy) {
$this->data = $data;
$this->sortBy = $sortBy;
$order = $this->listTree($data, 0, 0);
$this->reorder($order[0]);
return $this->result;
}
}

View file

@ -0,0 +1,41 @@
<?php
abstract class Rule_Abstract
{
public $field;
protected $errorMsg;
protected $ctx;
public function __construct($field, $errorMsg)
{
$this->field = $field;
$this->errorMsg = $errorMsg;
}
public function setName($field)
{
$this->field = $field;
return $this;
}
public function setErrorMsg($errorMsg)
{
$this->errorMsg = $errorMsg;
return $this;
}
public function getErrorMsg()
{
return $this->errorMsg;
}
public function isValid(Collection $container, $status = null)
{
//
}
public function setContext($ctx)
{
$this->ctx = $ctx;
}
}

View file

@ -0,0 +1,2 @@
<?php
foreach (glob(dirname(__FILE__) . "/*.php") as $file) { require_once $file; }

View file

@ -0,0 +1,20 @@
<?php
require_once 'abstract.php';
/**
* Ïðîâåðêà íà ÷èñëî
*/
class Rule_Alpha extends Rule_Abstract
{
public function getErrorMsg()
{
return "Ïîëå äîëæíî ñîäåðæàòü òîëüêî áóêâû";
}
public function isValid(Collection $container, $status = null)
{
return ctype_alpha($container->get($this->field));
}
}

View file

@ -0,0 +1,59 @@
<?php
require_once 'abstract.php';
/**
* Ïðîâåðêà ôîðìàòà ýëåêòðîííîé ïî÷òû
*/
class Rule_Code extends Rule_Abstract
{
public function getErrorMsg()
{
return "Íåïðàâèëüíî óêàçàí ïåðñîíàëüíûé êîä";
}
function checkCode($code) {
foreach($code as $c) {
if (empty($c)) {
return false;
}
}
return true;
}
public function isValid(Collection $container, $status = null)
{
if ($status == 'update') return true;
$name = $this->field;
if (is_array($_POST[$name . '_code_genre'])) {
for($n = 0; $n < count($_POST[$name . '_code_genre']); $n++) {
$code = array(
$_POST[$name . '_code_genre'][$n],
$_POST[$name . '_code_f'][$n],
$_POST[$name . '_code_i'][$n],
$_POST[$name . '_code_o'][$n],
$_POST[$name . '_code_year'][$n],
$_POST[$name . '_code_month'][$n],
$_POST[$name . '_code_day'][$n]
);
if (!$this->checkCode($code)) {
return false;
}
}
return true;
} else {
$code = array(
$_POST[$name . '_code_genre'],
$_POST[$name . '_code_f'],
$_POST[$name . '_code_i'],
$_POST[$name . '_code_o'],
$_POST[$name . '_code_year'],
$_POST[$name . '_code_month'],
$_POST[$name . '_code_day']
);
return $this->checkCode($code);
}
}
}

View file

@ -0,0 +1,34 @@
<?php
require_once 'abstract.php';
/**
* Ïðîâåðêà ôîðìàòà äàòû
*/
class Rule_Count extends Rule_Abstract
{
public $size = 1;
public $max = false;
public function getErrorMsg()
{
return "Êîëè÷åñòâî çàïèñåé äîëæíî áûòü íå ìåííå {$this->size} è íå áîëåå {$this->max}";
}
function not_empty($s) {
return $s != "";
}
public function isValid(Collection $container, $status = null)
{
if (!$this->max) {
$this->max = $this->size;
}
$count = count(array_filter(array_map('trim',
explode(";", $container->get($this->field))), array($this, 'not_empty')));
return $count >= $this->size && $count <= $this->max;
}
}

View file

@ -0,0 +1,24 @@
<?php
require_once 'abstract.php';
/**
* Ïðîâåðêà ôîðìàòà äàòû
*/
class Rule_Date extends Rule_Abstract
{
private $split = "\\/";
public function getErrorMsg()
{
return "Íåâåðíûé ôîðìàò äàòû";
}
public function isValid(Collection $container, $status = null)
{
$pattern = "/^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{4})$/";
return (preg_match($pattern, $container->get($this->field), $matches)
&& checkdate($matches[2], $matches[1], $matches[3]));
}
}

View file

@ -0,0 +1,30 @@
<?php
require_once 'abstract.php';
/**
* Ïðîâåðêà ôîðìàòà ýëåêòðîííîé ïî÷òû
*/
class Rule_Email extends Rule_Abstract
{
public function getErrorMsg()
{
return "Íåâåðíûé ôîðìàò ýëåêòðîííîé ïî÷òû";
}
public function isValid(Collection $container, $status = null)
{
$user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\|\{\}~\']+';
$doIsValid = '(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]\.?)+';
$ipv4 = '[0-9]{1,3}(\.[0-9]{1,3}){3}';
$ipv6 = '[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7}';
$emails = explode(",", $container->get($this->field));
foreach ($emails as $email) {
// if (! preg_match("/^$user@($doIsValid|(\[($ipv4|$ipv6)\]))$/", $email)) return false;
if (! filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
}
return true;
}
}

View file

@ -0,0 +1,28 @@
<?php
require_once 'abstract.php';
/**
* Ïðîâåðêà ôîðìàòà ýëåêòðîííîé ïî÷òû
*/
class Rule_EmailList extends Rule_Abstract
{
public function getErrorMsg()
{
return "Íåâåðíûé ôîðìàò ýëåêòðîííîé ïî÷òû";
}
public function isValid(Collection $container, $status = null) {
$user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\|\{\}~\']+';
$doIsValid = '(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]\.?)+';
$ipv4 = '[0-9]{1,3}(\.[0-9]{1,3}){3}';
$ipv6 = '[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7}';
$emails = $container->get($this->field);
foreach ($emails as $email) {
// if (! preg_match("/^$user@($doIsValid|(\[($ipv4|$ipv6)\]))$/", $email)) return false;
if (! filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
}
return true;
}
}

View file

@ -0,0 +1,28 @@
<?php
require_once 'abstract.php';
/**
* Ïðîâåðêà íà ðàâåíòñòâî äâóõ ïîëåé
*/
class Rule_Match extends Rule_Abstract
{
public $same;
public function getErrorMsg()
{
return "Ïîëÿ íå ñîâïàäàþò";
}
/* public function __construct($field, $refField, $errorMsg)
{
$this->field = $field;
$this->refField = $refField;
$this->errorMsg = $errorMsg;
}
*/
public function isValid(Collection $container, $status = null) {
return (strcmp($container->get($this->field), $container->get($this->same)) == 0);
}
}

View file

@ -0,0 +1,25 @@
<?php
require_once 'abstract.php';
class Rule_Notnull extends Rule_Abstract
{
public function getErrorMsg()
{
return "Ïîëå íå äîëæíî áûòü ïóñòûì";
}
public function isValid(Collection $container, $status = null)
{
$data = $container->get($this->field);
if (is_array($data)) {
foreach($data as $c) {
if (trim($c) != '') return true;
}
return false;
} else {
$value = trim($data);
return $value != '';
}
}
}

View file

@ -0,0 +1,19 @@
<?php
require_once 'abstract.php';
/**
* Ïðîâåðêà íà ÷èñëî
*/
class Rule_Numeric extends Rule_Abstract
{
public function getErrorMsg()
{
return "Çíà÷åíèå ïîëÿ äîëæíî áûòü ÷èñëîì";
}
public function isValid(Collection $container, $status = null)
{
return (is_numeric($container->get($this->field)));
}
}

View file

@ -0,0 +1,35 @@
<?php
require_once 'abstract.php';
/**
* Ïðîâåðêà ôîðìàòà âðåìåíè
*/
class Rule_Time extends Rule_Abstract
{
private $split = ":";
public function getErrorMsg()
{
return "Íåâåðíûé ôîðìàò âðåìåíè";
}
static function checktime($hour, $minute)
{
if ($hour > -1 && $hour < 24 && $minute > -1 && $minute < 60) {
return true;
}
}
public function isValid(Collection $container, $status = null)
{
$tmp = explode($this->split, $container->get($this->field), 2);
if ($tmp) {
if (self::checktime ($tmp[0], $tmp[1])) {
return true;
}
}
return false;
}
}

View file

@ -0,0 +1,20 @@
<?php
require_once 'abstract.php';
/**
* Ïðîâåðêà ôîðìàòà âðåìåíè
*/
class Rule_Unique extends Rule_Abstract
{
public function getErrorMsg()
{
return $this->ctx->getMessage();
}
public function isValid(Collection $container, $status = null)
{
return $this->ctx->isUnique($container->get($this->field), $status);
}
}

View file

@ -0,0 +1,118 @@
<?php
/**
* Ïðîâåðêà êîëëåêöèè
*/
class Validator
{
protected $chain = array(); // Ìàññèâ ïðàâèë
protected $errorMsg = array(); // Ìàññèâ îøèáîê
/**
* Äîáàâëåíèå ñïèñêà ïðàâèë â ñïåöèàëüíîì ôîðìàòå
* array(array('name' => fieldname, 'validate' => ruletext), ...)
* fieldname - Èìÿ ïåðåìåíîé äëÿ ïðîâåðêè
* ruletext - Îïèñàíèå ïðàâèëà ñì. ôîðìàò ïðàâèëà íèæå
*/
public function addRuleList(array $input)
{
require_once "core/validator/rule/all.php";
$type = array(
'date' => 'Rule_Date',
'email' => 'Rule_Email',
'emaillist'=> 'Rule_EmailList',
'match' => 'Rule_Match',
'time' => 'Rule_Time',
'alpha' => 'Rule_Alpha',
'require' => 'Rule_Notnull',
'numeric' => 'Rule_Numeric',
'unique' => 'Rule_Unique',
'count' => 'Rule_Count',
'code' => 'Rule_Code'
);
// Ðàçáîð ïðàâèëà ïðîâåðêè
// Ôîðìàò ïðàâèëà 'rule1|rule2,param1=value1|rule3,param1=value1,param2=value2'
foreach ($input as $value) {
// Ñïèñîê ïðàâèë
if (! isset($value['validate'])) continue;
$rules = explode("|", $value['validate']);
foreach ($rules as $rule) {
// Ñïèñîê ïàðàìåòðîâ ïðàâèëà
$rule_param = explode(",", $rule);
$name = array_shift($rule_param);
if (isset($type[$name])) {
$constructor = $type[$name]; // "Rule_" . ucfirst($name)
$rule = new $constructor($value['name'], false); // Íóæíû øàáëîííûå ñîîáùåíèÿ äëÿ ïðàâèë
if (isset($value['context'])) {
$rule->setContext($value['context']);
}
foreach ($rule_param as $param) {
// Èìÿ è çíà÷åíèå ïàðàìåòðà
list($name, $value) = explode("=", $param);
$rule->$name = $value;
}
$this->addRule($rule);
}
}
}
}
public function addRule(&$rule)
{
if (is_array($rule)) {
$this->chain = array_merge($this->chain, $rule);
} else {
$this->chain[] = $rule;
}
}
public function Skip($rule, $container) // -> Rule_Abstract
{
if ($rule instanceof Rule_Notnull) {
return false;
} else {
$data = $container->get($rule->field);
if (!is_array($data)) {
$value = trim($data);
return $value == '';
}
}
}
public function validate(Collection $container, $rule = null, $status = null)
{
if ($rule) {
$this->chain = $rule;
}
$this->errorMsg = array();
foreach ($this->chain as $key => $rule) {
if (!$this->Skip($rule, $container) && !$rule->isValid($container, $status)) {
$name = $rule->field;
$this->errorMsg[$name] = $rule->getErrorMsg();
}
}
return $this->isValid();
}
public function addError($name, $message)
{
$this->errorMsg[$name] = $message;
}
public function isError()
{
return !empty($this->errorMsg);
}
public function isValid()
{
return empty($this->errorMsg);
}
public function getErrorMsg()
{
return $this->errorMsg;
}
}

298
core/view/compositeview.php Normal file
View file

@ -0,0 +1,298 @@
<?php
class _View_Composite // AbstractCompositeView
{
protected $_section = array(); // Âëîæåííûå øàáëîíû
// Áëîêè
protected $_stylesheet = array(); // Ìàññèâ ñòèëåé òåêóùåãî øàáëîíà
protected $_script = array(); // Ìàññèâ ñêðèïòîâ òåêóùåãî øàáëîíà
protected $_scriptstring = array();
protected $_startup = array();
protected $_title = null; // Çàãîëîâîê òåêóùåãî øàáëîíà
public $alias = array();
function __construct()
{
}
/**
* Ñâÿçûâåò ïåðåìåííóþ ñ âëîæåííûì øàáëîíîì
*
* @param string $section ïåðåìåííàÿ øàáëîíà
* @param CompositeView $view âëîæåííûé øàáëîí
*/
public function setView($section, /*CompositeView*/ $view)
{
$this->_section [$section] = $view;
}
public function jGrowl($message, $args)
{
$this->addScriptRaw('$.jGrowl("' . $message . '", ' . json::encode($args) . ");\n", true);
}
public function setGlobal($name, $args)
{
$this->addScriptRaw("var " . $name . " = " . json::encode($args) . ";\n", false);
}
/**
* Äîáàâëÿåò ñêèïò ê òåêóùåìó øàáëîíó
*
* @param string $name ïóòü ê ñêðèïòó
*/
public function addScript($name)
{
$this->_script [] = $name;
}
/**
* Äîáàâëÿåò êîä ñêèïòà ê òåêóùåìó øàáëîíó
*
* @param string $name ñòðîêà javascript êîäà
*/
public function addScriptRaw($name, $startup = false)
{
if ($startup) {
$this->_startup [] = $name;
} else {
$this->_scriptstring [] = $name;
}
}
/**
* Äîáàâëÿåò ñòèëè ê òåêóùåìó øàáëîíó
*
* @param string $name ïóòü ê ñòèëþ
*/
public function addStyleSheet($name)
{
$this->_stylesheet [] = $name;
}
/**
* Ðåêóðñèâíî èçâëåêàåò èç çíà÷åíèå ñâîéñòâà îáüåêòà
*
* @param string $list Èìÿ ñâîéñòâà
* @param boolean $flatten
*/
private function doTree($list, $flatten = true) {
$result = ($flatten == true) ? $this->$list : array($this->$list);
foreach ($this->_section as $key => $value) {
if (is_object($value)) $result = array_merge($value->doTree($list, $flatten), $result);
}
return $result;
}
/**
* Ìàññèâ èìåí ôàéëîâ ñêðèïòîâ
*
* return array
*/
public function getScripts()
{
return $this->doTree('_script');
}
function resolveAlias($alias, $list)
{
$result = array();
foreach($list as $item) {
$result [] = strtr($item, $alias);
}
return $result;
}
/**
* Ñòðîêà ñî ñêðèïòîì
*
* @return string
*/
public function getScriptRaw()
{
return implode("\n", $this->doTree('_scriptstring'));
}
public function getScriptStartup()
{
return implode("\n", $this->doTree('_startup'));
}
/*abstract*/ public function set($key, $value)
{
}
/**
* Ìàññèâ èìåí ôàéëîâ ñòèëåé
*
* return array
*/
public function getStyleSheet()
{
return $this->doTree('_stylesheet');
}
/**
* Îáðàáîòêà âñåõ âëîæåííûõ øàáëîíîâ
*
* @return string
*/
public function execute()
{
foreach ($this->_section as $key => $value) {
$this->set($key, (is_object($value)) ? $value->execute() : $value); // ?
}
}
/**
* Óñòàíîâêà çàãîëîâêà øàáëîíà
*
* @param string $title
*/
public function setTitle($title)
{
$this->_title = $title;
}
private function isNotNull($title)
{
return $title !== null;
}
/**
* Îáùàÿ ñòðîêà çàãîëîâêà
*/
public function getTitle()
{
return implode(" - ", array_filter($this->doTree('_title', false), array($this, 'isNotNull')));
}
private function findGroup($groups, $file)
{
foreach($groups as $key => $group) {
if(in_array($file, $group)) {
return $key;
}
}
return false;
}
private function groupFiles(array $list, $debug)
{
$debug = ($debug) ? 'debug=1' : '';
$path = parse_url(WWW_PATH, PHP_URL_PATH);
$list = array_reverse($list);
// Ãðóïïû íóæíî ïåðåäâàâàòü êàê ïàðàìåòð !!!
$groups = array(
'table' => array($path . '/js/table.js', $path . '/js/listtable.js',
$path . '/js/page.js', $path . '/js/pagemenu.js'),
'base' => array($path . '/js/admin.js', $path . '/js/cookie.js'),
);
$use = array();
$result = array();
foreach ($list as $file) {
$name = $this->findGroup($groups, $file);
if($name) {
$use [$name] = 1;
} else {
$result [] = $file;
}
}
$list = array();
foreach ($use as $name => $value) {
$list [] = WWW_PATH . "/min/?$debug&f=" . implode(",", $groups[$name]);
}
return array_merge($list, $result);
}
/**
* Îáðàáîòêà øàáëîíà
*
* @return string
*/
public function render()
{
$alias = $this->doTree('alias');
// require_once 'minify.php';
// Ñêðèïòû è ñòèëè
$this->set('scripts', array_unique($this->groupFiles($this->resolveAlias($alias, $this->getScripts()), false)));
$this->set('stylesheet', array_unique($this->groupFiles($this->resolveAlias($alias, $this->getStyleSheet()), false)));
$this->set('scriptstring', $this->getScriptRaw());
$this->set('startup', $this->getScriptStartup());
$this->set('title', $this->getTitle());
//
return $this->execute(); // execute+phptal ??
}
function setAlias($alias)
{
$this->alias = $alias;
}
function addAlias($name, $path)
{
$this->alias['${' . $name . '}'] = $path;
$this->set($name, $path);
}
function loadImports($importFile)
{
// Ïîäêëþ÷åíèå ñòèëåé è ñêðèïòîâ
if (file_exists($importFile)) {
$import = file_get_contents($importFile);
$files = explode("\n", $import);
foreach ($files as $file) {
if (strpos($file, ".js") !== false) {
$this->addScript(strtr(trim($file), $this->alias));
} else if(strpos($file, ".css") !== false) {
$this->addStyleSheet(strtr(trim($file), $this->alias));
}
}
}
}
}
// CompositeView+PHPTAL
class View_Composite extends _View_Composite
{
private $tal;
function __construct($file)
{
parent::__construct($file);
require_once "PHPTAL.php";
$this->tal = new PHPTAL($file);
$this->tal->setEncoding('WINDOWS-1251'); // PHP_TAL_DEFAULT_ENCODING !!
$this->tal->stripComments(true);
}
function set($key, $val)
{
if ($key == 'title') {
$this->setTitle($val);
}
$this->tal->set($key, $val);
}
function __set($key, $val)
{
$this->tal->set($key, $val);
}
function setTranslator($tr)
{
$this->tal->setTranslator($tr);
}
function execute()
{
parent::execute();
// postProcess
return $this->tal->execute();
}
}

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