This commit is contained in:
Петрищев Алексей 2025-11-13 16:21:12 +03:00
parent 7d96bc9b05
commit 279dc69a29
494 changed files with 212487 additions and 222 deletions

3
app/.config Normal file
View File

@ -0,0 +1,3 @@
mysql login is: coresevaangels
mysql password is: OI0nffBu
mysql dbname is: coresevaangels

4
app/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/public_html/assets/.sass-cache/249aff91a402ca71c71b9b435f36ede940d9c347/*.scssc
/public_html/assets/.sass-cache/ad15a9450a1a9db0dfc2799403cf03067aa8ee32/*.scssc
/public_html/assets/.sass-cache/eec1b91ea5f292b0302cc627790fb17a12e40180/*.scssc
/public_html/assets/.sass-cache/faf9fdf4101f3cba59e35eca2e76f7c3fe669eb0/*.scssc

6
app/composer.json Normal file
View File

@ -0,0 +1,6 @@
{
"require": {
"friendsofphp/php-cs-fixer": "^3.39",
"filp/whoops": "^2.16"
}
}

1934
app/composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
<?php
/**
* Файл с доступами к внешним API и ресурсам
*/
define ('_ROOT_USER_ID', -999 );
define ('_SITE_TITLE_', 'Название сайта');
define ('_PHONE_PREFIX', '7');
define('_PHONE_LEN', 10) ;
?>

10
app/config/accounts.php Normal file
View File

@ -0,0 +1,10 @@
<?php
if (file_exists(dirname(__FILE__) . '/accounts.prod.php')) {
require_once('accounts.prod.php');
} elseif (file_exists(dirname(__FILE__) . '/accounts.dev.php')) {
require_once('accounts.dev.php');
} else {
die('config file not found');
}
?>

21
app/config/db.cfg.dev.php Normal file
View File

@ -0,0 +1,21 @@
<?php
$core_db->connect('mariadb', 'app_user', 'app_pass', 'app_db');
$core_db->q('SET NAMES utf8');
$server_name = 'localhost'; // Основной домен сайта
if ($_SERVER['HTTPS'] == 'on' ) {
define('_SITE_SCHEMA_', 'https');
} else {
define('_SITE_SCHEMA_', 'http');
}
define('_SITE_ROOT_', _SITE_SCHEMA_.'://'.$server_name . '/' . _SITE_PATH );
define('_STATIC_ROOT_', _SITE_SCHEMA_.'://'.$server_name . '/' );
define('_SHOP_ROOT_', _SITE_SCHEMA_.'://'.$server_name .'/');
define ('_COOKIE_DOMAIN_', $server_name );
?>

10
app/config/db.cfg.php Normal file
View File

@ -0,0 +1,10 @@
<?php
if (file_exists(dirname(__FILE__) . '/db.cfg.prod.php')) {
require_once('db.cfg.prod.php');
} elseif (file_exists(dirname(__FILE__) . '/db.cfg.dev.php')) {
require_once('db.cfg.dev.php');
} else {
die('config file not found');
}
?>

View File

@ -0,0 +1,350 @@
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card shadow-sm mb-3">
<div class="card-header d-flex justify-content-between align-items-center">
<div>
<h5 class="mb-0">Редактирование участков</h5>
@if(!empty($cat->cat_name))
<small class="text-muted d-block">Раздел: {{ $cat->cat_name }}</small>
@endif
</div>
<button type="button" class="btn btn-primary btn-sm" id="btn-create-zone">
<i class="fa fa-draw-polygon mr-1"></i> Создать участок
</button>
</div>
<div class="card-body p-0">
<div id="map" class="w-100 map-container"></div>
</div>
</div>
</div>
</div>
</div>
<style>
#newzoneedit {
display: none;
}
.map-container {
height: 600px;
min-height: 400px;
}
.balloon-response {
font-size: 0.875rem;
}
</style>
<script type="text/javascript" src="assets/js/jquery.ajaxform.js"></script>
<script src="//api-maps.yandex.ru/2.1/?lang=ru_RU" type="text/javascript"></script>
<script>
// Конфиг для запросов
var POLYGON_CONFIG = {
baseUrl: @json('?cat=' . $cat->cat) // строка вида "?cat=admin_polygon"
};
var PolygonEditor = {
myMap: null,
myPolygon: null,
isDrawing: false,
poligons: {},
init: function () {
var self = this;
self.myMap = new ymaps.Map('map', {
center: [59.859605, 30.340733],
zoom: 14,
controls: ['smallMapDefaultSet']
});
// Кнопка создания участка
$('#btn-create-zone').on('click', function () {
if (!self.isDrawing) {
self.startDrawing();
} else {
self.cancelDrawing();
}
});
// Рендер существующих участков
@if (!empty($rows))
@foreach($rows as $row)
self.addPolygon(
{!! $row['coords'] !!},
{{ (int)$row['id'] }},
{!! json_encode($row['title']) !!}
);
@endforeach
@endif
},
setDrawButtonState: function (active) {
this.isDrawing = !!active;
var $btn = $('#btn-create-zone');
if (this.isDrawing) {
$btn
.removeClass('btn-primary')
.addClass('btn-danger')
.html('<i class="fa fa-check mr-1"></i> Завершить рисование');
} else {
$btn
.removeClass('btn-danger')
.addClass('btn-primary')
.html('<i class="fa fa-draw-polygon mr-1"></i> Создать участок');
}
},
startDrawing: function () {
var self = this;
if (self.isDrawing) {
return;
}
self.myPolygon = new ymaps.Polygon([], {}, {
editorDrawingCursor: "crosshair",
editorMaxPoints: 999,
fillColor: '#ed4543',
strokeColor: '#ed4543',
fillOpacity: 0.6,
strokeWidth: 1
});
self.myMap.geoObjects.add(self.myPolygon);
self.attachEditorMonitor(self.myPolygon, function () {
self.stopDrawing();
});
self.myPolygon.editor.startDrawing();
self.setDrawButtonState(true);
},
cancelDrawing: function () {
if (!this.myPolygon) {
this.setDrawButtonState(false);
return;
}
this.myPolygon.editor.stopDrawing();
this.myMap.geoObjects.remove(this.myPolygon);
this.myPolygon = null;
this.setDrawButtonState(false);
},
stopDrawing: function () {
var self = this;
if (!self.myPolygon) {
self.setDrawButtonState(false);
return;
}
var coords = self.myPolygon.geometry.getCoordinates();
self.myPolygon.editor.stopDrawing();
self.myMap.geoObjects.remove(self.myPolygon);
self.myPolygon = null;
self.setDrawButtonState(false);
// ВАЖНО: используем сигнатуру $.post(url, data, success, dataType)
$.post(
POLYGON_CONFIG.baseUrl + '&act=editgeom&id=0',
{ geom: coords },
function (data) {
if (data && data.id && data.id !== 0) {
self.addPolygon(coords, data.id, data.title || '');
}
},
'json'
).fail(function () {
console.error('Ошибка сохранения нового участка');
});
},
addPolygon: function (coords, id, title) {
var self = this;
// $.get(url, success, dataType)
$.get(
POLYGON_CONFIG.baseUrl + '&act=getForm&id=' + id,
function (params) {
params = params || {};
self._addPolygonHtml(
coords,
id,
params.title || title || '',
params.html || '',
params.color || '#00FF00'
);
},
'json'
).fail(function () {
console.error('Ошибка получения формы участка');
});
},
_addPolygonHtml: function (coords, id, title, html, fillcolor) {
var self = this;
fillcolor = fillcolor || "#00FF00";
self.poligons[id] = new ymaps.GeoObject({
geometry: {
type: "Polygon",
coordinates: coords,
fillRule: "nonZero"
},
properties: {
myid: id,
balloonContentHeader: title,
balloonContent: html,
balloonContentFooter:
'<div class="mt-2">' +
'<a href="#" onclick="PolygonEditor.editPolygon(' + id + ');return false;">Редактировать контур</a>' +
' | ' +
'<a href="#" class="text-danger" onclick="PolygonEditor.removePolygon(' + id + ');return false;">Удалить участок</a>' +
'</div>'
}
}, {
fillColor: fillcolor,
strokeColor: '#0000FF',
opacity: 0.5,
strokeWidth: 1,
strokeStyle: 'shortdash'
});
self.attachEditorMonitor(self.poligons[id], function (e) {
if (e.originalEvent && e.originalEvent.target) {
var tid = e.originalEvent.target.properties.get('myid');
var tcoords = e.originalEvent.target.geometry.getCoordinates();
if (!tid) {
self.stopDrawing();
return;
}
$.post(
POLYGON_CONFIG.baseUrl + '&act=editgeom&id=' + tid,
{ geom: tcoords },
function (data) {
if (data && data.id && data.id !== 0) {
self.addPolygon(tcoords, data.id, data.title || '');
}
},
'json'
).fail(function () {
console.error('Ошибка обновления контура участка');
});
}
});
self.myMap.geoObjects.add(self.poligons[id]);
},
editPolygon: function (id) {
var polygon = this.poligons[id];
if (!polygon) {
return;
}
var self = this;
self.myPolygon = polygon;
self.myMap.geoObjects.add(self.myPolygon);
self.attachEditorMonitor(self.myPolygon, function () {
self.stopDrawing();
});
self.myPolygon.editor.startDrawing();
self.setDrawButtonState(true);
},
removePolygon: function (id) {
var self = this;
if (!self.poligons[id]) {
return;
}
$.get(
POLYGON_CONFIG.baseUrl + '&act=remove&id=' + id,
function () {
self.myMap.geoObjects.remove(self.poligons[id]);
delete self.poligons[id];
}
).fail(function () {
console.error('Ошибка удаления участка');
});
},
submitForm: function (id, idn) {
var self = this;
var $resp = $('#resp' + idn);
var options = {
dataType: 'json',
success: function (params) {
params = params || {};
var data = params.html || '';
$resp
.addClass('balloon-response')
.html('<span class="text-success">Данные сохранены</span>' + data);
if (self.poligons[id]) {
self.poligons[id].properties.set('balloonContent', data);
if (params.color) {
self.poligons[id].options.set('fillColor', params.color);
}
}
},
error: function () {
$resp
.addClass('balloon-response')
.html('<span class="text-danger">Ошибка сохранения</span>');
}
};
$('#form' + idn).ajaxSubmit(options);
$resp.html("<img src='img/loader.gif' alt='' class='img-fluid'>");
return false;
},
attachEditorMonitor: function (polygon, onStopCallback) {
var stateMonitor = new ymaps.Monitor(polygon.editor.state);
stateMonitor.add("drawing", function (newValue) {
polygon.options.set("strokeColor", newValue ? '#FF0000' : '#0000FF');
});
polygon.events.add(['editorstatechange'], function (e) {
if (
e.originalEvent &&
e.originalEvent.originalEvent &&
e.originalEvent.originalEvent.originalEvent &&
e.originalEvent.originalEvent.originalEvent.newDrawing === false &&
e.originalEvent.originalEvent.originalEvent.oldDrawing === true
) {
if (typeof onStopCallback === 'function') {
onStopCallback(e);
}
}
});
}
};
// Для совместимости со старой формой: onsubmit="return submit_form(id, idn)"
function submit_form(id, idn) {
return PolygonEditor.submitForm(id, idn);
}
ymaps.ready(function () {
PolygonEditor.init();
});
</script>

View File

@ -0,0 +1,352 @@
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card shadow-sm mb-3">
<div class="card-header d-flex justify-content-between align-items-center">
<div>
<h5 class="mb-0">Редактирование участков</h5>
<?php if(!empty($cat->cat_name)): ?>
<small class="text-muted d-block">Раздел: <?php echo \htmlentities($cat->cat_name, ENT_QUOTES, 'UTF-8', false); ?></small>
<?php endif; ?>
</div>
<button type="button" class="btn btn-primary btn-sm" id="btn-create-zone">
<i class="fa fa-draw-polygon mr-1"></i> Создать участок
</button>
</div>
<div class="card-body p-0">
<div id="map" class="w-100 map-container"></div>
</div>
</div>
</div>
</div>
</div>
<style>
#newzoneedit {
display: none;
}
.map-container {
height: 600px;
min-height: 400px;
}
.balloon-response {
font-size: 0.875rem;
}
</style>
<script type="text/javascript" src="assets/js/jquery.ajaxform.js"></script>
<script src="//api-maps.yandex.ru/2.1/?lang=ru_RU" type="text/javascript"></script>
<script>
// Конфиг для запросов
var POLYGON_CONFIG = {
baseUrl: <?php echo json_encode('?cat=' . $cat->cat, 15, 512); ?> // строка вида "?cat=admin_polygon"
};
var PolygonEditor = {
myMap: null,
myPolygon: null,
isDrawing: false,
poligons: {},
init: function () {
var self = this;
self.myMap = new ymaps.Map('map', {
center: [59.859605, 30.340733],
zoom: 14,
controls: ['smallMapDefaultSet']
});
// Кнопка создания участка
$('#btn-create-zone').on('click', function () {
if (!self.isDrawing) {
self.startDrawing();
} else {
self.cancelDrawing();
}
});
// Рендер существующих участков
<?php if(!empty($rows)): ?>
<?php $__currentLoopData = $rows; $this->addLoop($__currentLoopData);$this->getFirstLoop();
foreach($__currentLoopData as $row): $loop = $this->incrementLoopIndices(); ?>
self.addPolygon(
<?php echo $row['coords']; ?>,
<?php echo \htmlentities((int)$row['id'], ENT_QUOTES, 'UTF-8', false); ?>,
<?php echo json_encode($row['title']); ?>
);
<?php endforeach; $this->popLoop(); $loop = $this->getFirstLoop(); ?>
<?php endif; ?>
},
setDrawButtonState: function (active) {
this.isDrawing = !!active;
var $btn = $('#btn-create-zone');
if (this.isDrawing) {
$btn
.removeClass('btn-primary')
.addClass('btn-danger')
.html('<i class="fa fa-check mr-1"></i> Завершить рисование');
} else {
$btn
.removeClass('btn-danger')
.addClass('btn-primary')
.html('<i class="fa fa-draw-polygon mr-1"></i> Создать участок');
}
},
startDrawing: function () {
var self = this;
if (self.isDrawing) {
return;
}
self.myPolygon = new ymaps.Polygon([], {}, {
editorDrawingCursor: "crosshair",
editorMaxPoints: 999,
fillColor: '#ed4543',
strokeColor: '#ed4543',
fillOpacity: 0.6,
strokeWidth: 1
});
self.myMap.geoObjects.add(self.myPolygon);
self.attachEditorMonitor(self.myPolygon, function () {
self.stopDrawing();
});
self.myPolygon.editor.startDrawing();
self.setDrawButtonState(true);
},
cancelDrawing: function () {
if (!this.myPolygon) {
this.setDrawButtonState(false);
return;
}
this.myPolygon.editor.stopDrawing();
this.myMap.geoObjects.remove(this.myPolygon);
this.myPolygon = null;
this.setDrawButtonState(false);
},
stopDrawing: function () {
var self = this;
if (!self.myPolygon) {
self.setDrawButtonState(false);
return;
}
var coords = self.myPolygon.geometry.getCoordinates();
self.myPolygon.editor.stopDrawing();
self.myMap.geoObjects.remove(self.myPolygon);
self.myPolygon = null;
self.setDrawButtonState(false);
// ВАЖНО: используем сигнатуру $.post(url, data, success, dataType)
$.post(
POLYGON_CONFIG.baseUrl + '&act=editgeom&id=0',
{ geom: coords },
function (data) {
if (data && data.id && data.id !== 0) {
self.addPolygon(coords, data.id, data.title || '');
}
},
'json'
).fail(function () {
console.error('Ошибка сохранения нового участка');
});
},
addPolygon: function (coords, id, title) {
var self = this;
// $.get(url, success, dataType)
$.get(
POLYGON_CONFIG.baseUrl + '&act=getForm&id=' + id,
function (params) {
params = params || {};
self._addPolygonHtml(
coords,
id,
params.title || title || '',
params.html || '',
params.color || '#00FF00'
);
},
'json'
).fail(function () {
console.error('Ошибка получения формы участка');
});
},
_addPolygonHtml: function (coords, id, title, html, fillcolor) {
var self = this;
fillcolor = fillcolor || "#00FF00";
self.poligons[id] = new ymaps.GeoObject({
geometry: {
type: "Polygon",
coordinates: coords,
fillRule: "nonZero"
},
properties: {
myid: id,
balloonContentHeader: title,
balloonContent: html,
balloonContentFooter:
'<div class="mt-2">' +
'<a href="#" onclick="PolygonEditor.editPolygon(' + id + ');return false;">Редактировать контур</a>' +
' | ' +
'<a href="#" class="text-danger" onclick="PolygonEditor.removePolygon(' + id + ');return false;">Удалить участок</a>' +
'</div>'
}
}, {
fillColor: fillcolor,
strokeColor: '#0000FF',
opacity: 0.5,
strokeWidth: 1,
strokeStyle: 'shortdash'
});
self.attachEditorMonitor(self.poligons[id], function (e) {
if (e.originalEvent && e.originalEvent.target) {
var tid = e.originalEvent.target.properties.get('myid');
var tcoords = e.originalEvent.target.geometry.getCoordinates();
if (!tid) {
self.stopDrawing();
return;
}
$.post(
POLYGON_CONFIG.baseUrl + '&act=editgeom&id=' + tid,
{ geom: tcoords },
function (data) {
if (data && data.id && data.id !== 0) {
self.addPolygon(tcoords, data.id, data.title || '');
}
},
'json'
).fail(function () {
console.error('Ошибка обновления контура участка');
});
}
});
self.myMap.geoObjects.add(self.poligons[id]);
},
editPolygon: function (id) {
var polygon = this.poligons[id];
if (!polygon) {
return;
}
var self = this;
self.myPolygon = polygon;
self.myMap.geoObjects.add(self.myPolygon);
self.attachEditorMonitor(self.myPolygon, function () {
self.stopDrawing();
});
self.myPolygon.editor.startDrawing();
self.setDrawButtonState(true);
},
removePolygon: function (id) {
var self = this;
if (!self.poligons[id]) {
return;
}
$.get(
POLYGON_CONFIG.baseUrl + '&act=remove&id=' + id,
function () {
self.myMap.geoObjects.remove(self.poligons[id]);
delete self.poligons[id];
}
).fail(function () {
console.error('Ошибка удаления участка');
});
},
submitForm: function (id, idn) {
var self = this;
var $resp = $('#resp' + idn);
var options = {
dataType: 'json',
success: function (params) {
params = params || {};
var data = params.html || '';
$resp
.addClass('balloon-response')
.html('<span class="text-success">Данные сохранены</span>' + data);
if (self.poligons[id]) {
self.poligons[id].properties.set('balloonContent', data);
if (params.color) {
self.poligons[id].options.set('fillColor', params.color);
}
}
},
error: function () {
$resp
.addClass('balloon-response')
.html('<span class="text-danger">Ошибка сохранения</span>');
}
};
$('#form' + idn).ajaxSubmit(options);
$resp.html("<img src='img/loader.gif' alt='' class='img-fluid'>");
return false;
},
attachEditorMonitor: function (polygon, onStopCallback) {
var stateMonitor = new ymaps.Monitor(polygon.editor.state);
stateMonitor.add("drawing", function (newValue) {
polygon.options.set("strokeColor", newValue ? '#FF0000' : '#0000FF');
});
polygon.events.add(['editorstatechange'], function (e) {
if (
e.originalEvent &&
e.originalEvent.originalEvent &&
e.originalEvent.originalEvent.originalEvent &&
e.originalEvent.originalEvent.originalEvent.newDrawing === false &&
e.originalEvent.originalEvent.originalEvent.oldDrawing === true
) {
if (typeof onStopCallback === 'function') {
onStopCallback(e);
}
}
});
}
};
// Для совместимости со старой формой: onsubmit="return submit_form(id, idn)"
function submit_form(id, idn) {
return PolygonEditor.submitForm(id, idn);
}
ymaps.ready(function () {
PolygonEditor.init();
});
</script>

View File

@ -0,0 +1,111 @@
<?php
class admin_cats extends module {
var $templ = "admin_cats.htm";
var $_get_vars = array( 'act', 'parentCat', 'id', 'mname' );
var $_loc_vars = array('templ');
function _on_() {
global $R, $db;
$tpl = $R->getTpl( $this->templ, 'body' );
$tmp = $this->r_subtree( '' );
$tpl = $R->parse( 'rows', $tmp, $tpl );
$tpl = $R->set( 'form', '', $tpl );
return $R->clear( $tpl );
}
function _on_edit() {
global $R;
$tpl = $R->getTpl( $this->templ, 'body' );
$obj = new cobject ('_sys_cat');
if (!$this->id && $this->parentCat ) {
$obj->set('parent_cat', $this->parentCat );
} else {
$obj->byId( $this->id );
}
$form = new form( $obj );
$tpl = $R->set( 'form', $form->render(), $tpl );
$tmp = $this->r_subtree( '' );
$tpl = $R->parse( 'rows', $tmp, $tpl );
return $R->clear( $tpl );
}
function _on_save_edit() {
global $cat;
$obj = new cobject ('_sys_cat');
$obj->lPost();
$obj->save();
$savedSql = $obj->save_sql;
$this->saveMigration($savedSql);
_redirect("?cat=" . $cat->cat . '&act=edit&id='.$obj->id);
}
function r_subtree( $cat, $level = 1 ) {
global $R, $core_db;
$tpl = $R->getTpl( $this->templ, 'row' );
$tplu = $R->getTpl( $this->templ, 'row_unvisible' );
$tpls = $R->getTpl( $this->templ, 'sep' );
$obj = new cobject( '_sys_cat' );
$db2 = $core_db->q( $obj->getSelect( ' AND `parent_cat` = "'.$cat.'" ORDER BY `_sys_order` ') );
while ( $db2->r() ) {
$obj->lRow( $db2 );
if ($obj->get('_sys_unvisible')) {
$tt = $obj->assign( $tplu );
} else {
$tt = $obj->assign( $tpl );
}
for( $i=0; $i<$level; $i++ ) {
$tt = $R->parse( 'seps', $tpls, $tt );
}
$tmp = $this->r_subtree($db2->f('cat_id'), ($level+1));
$out .= $R->parse( 'subrows', $tmp, $tt );
}
return $out;
}
function _on_getVars() {
$module = substr($this->mname,0,-4);
if(!$module) die('');
$obj = new cobject ('_sys_cat');
$data = explode(';', $obj->attrs['module']['templ']);
$path = $data[0];
require_once( _ENGINE_DIR . $path .'/' . $module.'.php' );
$tobj = new $module();
$html = '';
foreach($tobj->_loc_vars as $v) {
$html .= "<b>$"."$v</b>=".$tobj->$v.";<br>";
}
die($html);
}
function saveMigration($query) {
global $core_db;
$filename = date('Ymd-Hi') . "-user-cats.sql";
$f = fopen( _ENGINE_DIR . 'migrations/' . $filename, "a" );
fputs($f, $query . ";\n" );
fclose($f);
$core_db->q('SELECT apply_datetime FROM _sys_db_migrations WHERE `filename` = "'.db_escape_string($filename).'" ');
if (!$core_db->nr()) {
$core_db->q('INSERT INTO _sys_db_migrations (`filename`,`apply_datetime`) values ("'.db_escape_string($filename).'", "'.date('Y-m-d H:i:s').'" ) ');
}
}
}
?>

View File

@ -0,0 +1,109 @@
<?php
class admin_core_cats extends module {
var $templ = "admin_core_cats.htm";
var $_get_vars = array( 'act', 'parentCat', 'id', 'mname' );
var $_loc_vars = array('templ');
function _on_() {
global $R, $db;
$tpl = $R->getTpl( $this->templ, 'body' );
$tmp = $this->r_subtree( '' );
$tpl = $R->parse( 'rows', $tmp, $tpl );
$tpl = $R->set( 'form', '', $tpl );
return $R->clear( $tpl );
}
function _on_edit() {
global $R, $cat;
$tpl = $R->getTpl( $this->templ, 'body' );
$obj = new cobject ('_sys_cat_admin');
if (!$this->id && $this->parentCat ) {
$obj->set('parent_cat', $this->parentCat );
} else {
$obj->byId( $this->id );
}
$form = new form( $obj );
$tpl = $R->set( 'form', $form->render(), $tpl );
$tmp = $this->r_subtree( '' );
$tpl = $R->parse( 'rows', $tmp, $tpl );
return $R->clear( $tpl );
}
function _on_save_edit() {
global $cat;
$obj = new cobject ('_sys_cat_admin');
$obj->lPost();
$obj->save();
$savedSql = $obj->save_sql;
$this->saveMigration($savedSql);
_redirect("?cat=" . $cat->cat . '&act=edit&id='.$obj->id);
}
function r_subtree( $cat, $level = 1 ) {
global $R, $core_db;
$tpl = $R->getTpl( $this->templ, 'row' );
$tplu = $R->getTpl( $this->templ, 'row_unvisible' );
$tpls = $R->getTpl( $this->templ, 'sep' );
$obj = new cobject( '_sys_cat_admin' );
$db2 = $core_db->q( $obj->getSelect( ' AND `parent_cat` = "'.$cat.'" ORDER BY `_sys_order` ') );
while ( $db2->r() ) {
$obj->lRow( $db2 );
if ($obj->get('_sys_unvisible')) {
$tt = $obj->assign( $tplu );
} else {
$tt = $obj->assign( $tpl );
}
for( $i=0; $i<$level; $i++ ) {
$tt = $R->parse( 'seps', $tpls, $tt );
}
$tmp = $this->r_subtree($db2->f('cat_id'), ($level+1));
$out .= $R->parse( 'subrows', $tmp, $tt );
}
return $out;
}
function _on_getVars() {
$module = substr($this->mname,0,-4);
if(!$module) die('');
$obj = new cobject ('_sys_cat_admin');
$data = explode(';', $obj->attrs['module']['templ']);
$path = $data[0];
require_once( _ENGINE_DIR . $path .'/' . $module.'.php' );
$tobj = new $module();
$html = '';
foreach($tobj->_loc_vars as $v) {
$html .= "<b>$"."$v</b>=".$tobj->$v.";<br>";
}
die($html);
}
function saveMigration($query) {
global $core_db;
$filename = date('Ymd-Hi') . "-admin-cats.sql";
$f = fopen( _ENGINE_DIR . 'migrations/' . $filename, "a" );
fputs($f, $query . ";\n" );
fclose($f);
$core_db->q('SELECT apply_datetime FROM _sys_db_migrations WHERE `filename` = "'.db_escape_string($filename).'" ');
if (!$core_db->nr()) {
$core_db->q('INSERT INTO _sys_db_migrations (`filename`,`apply_datetime`) values ("'.db_escape_string($filename).'", "'.date('Y-m-d H:i:s').'" ) ');
}
}
}
?>

View File

@ -0,0 +1,141 @@
<?php
class admin_objects_all extends module {
var $_loc_vars = array( 'templ', 'del', 'add' );
var $_get_vars = array( 'act', 'id', 'obj_name' );
var $_post_vars = array( 'act', 'id', 'obj_name' );
var $obj;
var $templ = 'admin_objects_all.htm';
var $del = true;
var $add = true;
function _init() {
$this->obj = new cobject( $this->obj_name );
return parent::_init();
}
function _on_() {
global $R;
$db = $this->obj->getDB();
$tpl = $R->getTpl( $this->templ, 'body' );
$tplr = $R->getTpl( $this->templ, 'row' );
$tpltd = $R->getTpl( $this->templ, 'td' );
$tplth = $R->getTpl( $this->templ, 'th' );
$tpl_del_td = $R->getTpl( $this->templ, 'del_td' );
$tpl_del_th = $R->getTpl( $this->templ, 'del_th' );
foreach( $this->obj->attrs as $attr_name => $attrs ) {
if ( $attrs['hide'] ) continue;
$tt = $R->set('attr_name', $attrs['desc'], $tplth );
$tpl = $R->parse( 'head_cols', $tt, $tpl );
$tt = $R->set('attr_name', $attr_name, $tpltd );
$tplr = $R->parse( 'row_cols', $tt, $tplr);
}
if ( $this->del ) {
$tpl = $R->parse( 'head_cols', $tpl_del_th, $tpl );
$tplr = $R->parse( 'row_cols', $tpl_del_td, $tplr);
}
$db2 = $db->q( $this->obj->getSelectEx( 'COUNT(*) as `cnt`') );
$db2->r();
$size = $db2->f('cnt');
$pw = new Walker( $size );
$filter = new filter( $this->obj_name );
$filter->parse();
$tpl = $R->set( 'filter', $filter->getHTML() , $tpl);
$db2 = $db->q( $this->obj->getSelect( $filter->getSQL() . ' ORDER BY `ID` DESC ' . $pw->getSQL() ) );
while( $db2->r() ) {
$this->obj->lRow($db2);
$tt = $this->obj->assign( $tplr, true );
$tpl = $R->parse( 'rows', $tt, $tpl );
}
$this->obj->byId($this->id);
if ( !$this->id && !$this->add ) {
$tpl = $R->set( 'form', '' , $tpl);
} else {
$tpl = $R->set( 'form', $this->r_form() , $tpl);
$tpl = $R->set( 'id', intval($this->id), $tpl );
}
$tpl = $R->set( 'walker', $pw->getHTML() , $tpl);
$tpl = $R->set( 'cur_page', $pw->page , $tpl);
$tpl = $R->set( 'obj_name', $this->obj_name, $tpl );
$sql = "SELECT TABLE_COMMENT FROM `information_schema`.`TABLES` where TABLE_SCHEMA = '".$db->dbname."' and TABLE_NAME = '".$this->obj_name."' ";
$db2 = $db->q($sql);
$db2->nr();
$tpl = $R->set('obj_title', htmlspecialchars($db2->f('TABLE_COMMENT')), $tpl);
$tpl = $R->set( 'filter_url', $this->_get_filter_url(), $tpl );
return $R->clear( $tpl );
}
function _on_edit() {
global $R;
$this->obj->byId($this->id);
if ( $this->id || $this->add ) {
return $this->r_form();
}
return '';
}
function _on_copy() {
global $cat;
$this->obj->byId($this->id);
$this->obj->saveAsCopy();
_redirect('?cat=' . $cat->cat . '&obj_name='.$this->obj_name . '&id='. $this->obj->id.'&' . $this->_get_filter_url() .'&curpage='.$_GET['curpage'] );
}
function r_form() {
$form = new form( $this->obj );
$form->_parse();
$form->form['obj_name']['hidden'] = 0;
$form->form['obj_name']['html'] = '<input type="hidden" name="obj_name" value="'.$this->obj->obj_name.'">';
return $form->_html();
}
function _on_save_edit() {
global $cat;
if ( !$this->id && !$this->add ) _redirect('?cat=' . $cat->cat . '&obj_name='.$this->obj_name );
$this->obj->lPost();
if ( $this->obj->validate() ) {
$this->obj->save();
} else {
return $this->r_form();
}
_redirect('?cat=' . $cat->cat . '&obj_name='.$this->obj_name . '&' . $this->_get_filter_url() .'&curpage='.$_GET['curpage'] );
}
function _on_del() {
global $cat;
if ( $this->del ) {
$this->obj->byId( $this->id );
$this->obj->del();
}
_redirect('?cat=' . $cat->cat . '&obj_name='.$this->obj_name . '&' . $this->_get_filter_url() .'&curpage='.$_GET['curpage'] );
}
function _get_filter_url() {
foreach( $_GET as $k => $v ) {
if ( strpos($k, $this->obj_name.'_') === 0 ) {
$ret = '&'.$k.'='.$v;
}
}
return $ret;
}
}
?>

View File

@ -0,0 +1,119 @@
<?php
class admin_polygon extends module {
public $templ = "shop_admin_polygon.htm";
public $templBlade = 'admin_polygon';
public $_get_vars = [ 'act', 'id' ];
public $_post_vars = [ 'act', 'geom' ];
public $_loc_vars = ['obj_name'];
public function _init() {
$this->obj = new cobject($this->obj_name);
return parent::_init();
}
public function _on_() {
global $blade;
$data = [];
$db2 = $this->obj->getDB()->q($this->obj->getSelectEx('id, title, ASTEXT(`geom`) as `geom` '));
while($db2->nr()) {
$coords = $this->mysql2json($db2->f('geom'));
$row = [];
$row['coords'] = $coords;
$row['id'] = $db2->f('id');
$row['title'] = $db2->f('title');
$data['rows'][] = $row;
}
return $blade->run($this->getBladeTempl('main'), $data);
}
public function _on_save_edit() {
$this->obj->set_hidden('geom');
$this->obj->lPost();
$this->obj->save();
$this->id = $this->obj->id;
return $this->_ajax_getForm();
}
public function _ajax_getForm() {
$this->obj->byId($this->id);
$this->obj->set_hidden('geom');
$form = new form($this->obj);
$form->setTempl('attrs/poly_form.htm');
$formdata = $form->render();
$polycolor = $this->obj->get('color') ? $this->obj->get('color') : '#00FF00';
$returndata = ['html' => $formdata, 'color' => $polycolor, 'title' => $this->obj->get('title') ];
echo json_encode($returndata);
// echo $form->render();
die();
}
public function _ajax_editgeom() {
$id = $this->id;
$this->obj->byId($id);
if ($this->geom) {
if (!$this->obj->id) {
$this->obj->set('title', 'Новая зона');
$this->obj->save();
$id = $this->obj->id;
}
$data = [];
foreach ($this->geom[0] as $p) {
$data[] = $p[0] . ' '. $p[1];
}
$str = "POLYGON((".implode(",", $data)."))";
$sql = "UPDATE `".$this->obj_name."` SET `geom` = GeomFromText('".$str."') WHERE `id` = '".$id."' ";
$db2 = $this->obj->getDB()->q($sql);
$ret = [];
$ret['id'] = $id;
$ret['title'] = htmlspecialchars_decode($this->obj->get('title'));
echo json_encode($ret);
die();
}
$ret = [];
$ret['id'] = 0;
echo json_encode($ret);
die();
}
public function mysql2json($str) {
// POLYGON((59.94778267548529 30.047386140625,60.12503918773836 30.468986482421876,59.92986664045532 30.963371248046883,59.84083181279909 30.456626863281247,59.960180395813275 30.38933560351563,59.94778267548529 30.047386140625))
preg_match_all('/POLYGON\(\((.*?)\)\)/', $str, $arr);
$points = explode(',', $arr[1][0]);
foreach($points as $point) {
$ret[0][] = explode(' ', $point);
}
return json_encode($ret);
}
public function _ajax_remove() {
$this->obj->byId($this->id);
$this->obj->del();
echo '1';
die();
}
}
?>

View File

@ -0,0 +1,382 @@
<?php
class admin_schema extends module {
var $templ = "admin_schema.htm";
var $_get_vars = array( 'act', 'obj_name', 'attr_name' );
var $_post_vars = array( 'act', 'attr_name', 'attr_type', '_obj', 'obj_names', 'obj_title' );
var $obj_cache = array();
var $migrationPrefix = '';
function _init() {
$this->migrationPrefix = date('Ymd-Hi');
return parent::_init();
}
function _on_() {
global $R, $core_db;
$tpl = $R->getTpl( $this->templ, 'body' );
$tplr = $R->getTpl( $this->templ, 'row' );
$db2 = $core_db->q( "SELECT DISTINCT `obj_name` FROM `_sys_datatypes` ORDER BY `obj_name`" );
while( $db2->r() ) {
$tt = $R->set('obj_name', $db2->f('obj_name'), $tplr );
$tpl = $R->parse( 'rows', $tt, $tpl );
$this->obj_cache[] = $db2->f('obj_name');
}
$tpl = $R->set( 'form', $this->r_table(), $tpl );
return $R->clear( $tpl );
}
function r_table() {
global $R, $core_db;
if (!$this->obj_name) return;
$tpl = $R->getTpl( $this->templ, 'edit_table' );
$tplr = $R->getTpl( $this->templ, 'edit_table_row' );
$db2 = $core_db->q( 'SELECT * FROM `_sys_datatypes` WHERE `obj_name` = "' . $this->obj_name . '" ORDER BY `attr_order`' );
while( $db2->r() ) {
$tt = $R->set('name', $db2->f('attr_name'), $tplr );
$tt = $R->set('attr_desc', $db2->f('attr_desc'), $tt );
$tt = $R->set('attr_templ', $db2->f('attr_templ'), $tt );
$tt = $R->set('attr_order', $db2->f('attr_order'), $tt );
$tt = $R->set('attr_hide', $db2->f('attr_hide')?'checked':'', $tt );
$tt = $R->set('attr_mand', $db2->f('attr_mand')?'checked':'', $tt );
$tt = $R->set('attr_view', $this->r_types( $db2->f('attr_type') ), $tt );
$tpl = $R->parse( 'rows', $tt, $tpl );
}
$tpl = $R->set('obj_name', $this->obj_name, $tpl );
$tpl = $R->set('attr_view', $this->r_types(), $tpl );
$sql = "SELECT TABLE_COMMENT FROM `information_schema`.`TABLES` where TABLE_SCHEMA = '".$core_db->dbname."' and TABLE_NAME = '".$this->obj_name."' ";
$db2 = $core_db->q($sql);
$db2->nr();
$tpl = $R->set('obj_title', htmlspecialchars($db2->f('TABLE_COMMENT')), $tpl);
return $R->clear( $tpl );
}
function r_types( $val = '' ) {
global $loaded_attrs;
sort($loaded_attrs);
sort($this->obj_cache);
$html = '<option value="" selected>---</option>';
foreach ($loaded_attrs as $v ) {
$classname = 'attr_' . $v;
$size = $classname::getDBType();
//eval('$'."size = attr_$v::getDBType();");
switch( $v ) {
case 'LINK':
$html .= '<optgroup label="'.$v.'">';
foreach( $this->obj_cache as $obj_name ) {
$vv = $v . '|' . $obj_name;
$title = "LINK " . $obj_name;
if ( $vv == $val )
$html .= '<option value="' . $vv . '" selected>' . $title . " [$size]" .'</option>';
else
$html .= '<option value="' . $vv . '">' . $title . " [$size]" .'</option>';
}
$html .= '</optgroup>';
break;
case 'MLINK':
$html .= '<optgroup label="'.$v.'">';
foreach( $this->obj_cache as $obj_name ) {
$vv = $v . '|' . $obj_name;
$title = "MLINK " . $obj_name;
if ( $vv == $val )
$html .= '<option value="' . $vv . '" selected>' . $title . " [$size]" .'</option>';
else
$html .= '<option value="' . $vv . '">' . $title . " [$size]" .'</option>';
}
$html .= '</optgroup>';
break;
default:
if ( $v == $val )
$html .= '<option value="' . $v . '" selected>' . $v ." [$size]" . '</option>';
else
$html .= '<option value="' . $v . '">' . $v . " [$size]" .'</option>';
break;
}
}
return $html;
}
function _on_add_attr() {
global $cat, $core_db, $auth;
if (!$this->attr_name ) cdie('no attr name');
if (!$this->attr_type ) cdie('no attr type');
$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Создание атрибута" );
$this->do_add($this->obj_name, $this->attr_name, $this->attr_type);
_redirect('?cat=' .$cat->cat .'&obj_name='.$this->obj_name);
}
function do_add( $obj_name, $attr_name, $attr_type, $attr_title = '', $attr_templ = '', $attr_order = 100 ) {
global $cat, $core_db, $auth;
$sys_obj = false;
if ( ( strpos( $obj_name, '_sys_') !== false ) ) {
$sys_obj = true;
}
/* CREATE TABLE */
$sql = "CREATE TABLE IF NOT EXISTS `" . $obj_name . "` (";
$sql .= " `id` INT(12) NOT NULL AUTO_INCREMENT PRIMARY KEY ";
$sql .= ") ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci";
$core_db->q( $sql );
$this->sLog( $sql );
/* ADD Attribute */
$v = explode('|',$attr_type);
$v = $v[0];
eval('$'."size = attr_$v::getDBType();");
$sql = "ALTER TABLE `" . $obj_name . "` ADD `" . $attr_name . "` " . $size . " NOT NULL";
$core_db->q( $sql );
$this->sLog( $sql );
if (substr($attr_type,0,4) == 'LINK') {
/* ADD index */
$sql = "ALTER TABLE `" . $obj_name . "` ADD INDEX ( `" . $attr_name . "` )";
$core_db->q( $sql );
$this->sLog( $sql );
}
if ($attr_type == 'tree_object') {
/* ADD index */
$sql = "ALTER TABLE `" . $obj_name . "` ADD INDEX ( `" . $attr_name . "` )";
$core_db->q( $sql );
$this->sLog( $sql );
}
/* ADD to Datatype table */
$sql = 'REPLACE INTO `_sys_datatypes` (`obj_name`, `attr_name`,`attr_type`,`attr_desc`,`attr_templ`,`attr_order`) VALUES ("'.$obj_name.'","'.$attr_name.'","'.$attr_type.'","'.$attr_title.'","'.$attr_templ.'","'.$attr_order.'")';
$core_db->q( $sql );
$this->sLog( $sql );
}
function _on_do_urled() {
global $cat;
$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Создание атрибутов" );
$this->do_add($this->obj_name, 'title', 'input', 'Название','', 50);
$this->do_add($this->obj_name, 'url', 'full_url', 'Полный URL','prefix|cat_id',60 );
$this->do_add($this->obj_name, 'description', 'redactor_html', 'Текстовый блок');
$this->do_add($this->obj_name, 'page_description', 'input', 'seo description','',504);
$this->do_add($this->obj_name, 'page_h1', 'input', 'seo H1','',502);
$this->do_add($this->obj_name, 'page_keywords', 'input', 'seo keywords','',503);
$this->do_add($this->obj_name, 'page_title', 'input', 'seo title','',501);
$this->do_add($this->obj_name, '_sys_deleted', 'checkbox', 'Удалённый','', 1000);
$this->do_add($this->obj_name, '_sys_order', 'int12', 'Порядок сортировки','', 800);
$this->do_add($this->obj_name, '_sys_unvisible', 'checkbox', 'Невидимый','', 999);
$this->do_add($this->obj_name, '_sys_lastchange', 'datetime_modify', 'Последнее изменение','', 999);
_redirect('?cat=' .$cat->cat .'&obj_name='.$this->obj_name);
}
function _on_do_treeobj() {
global $cat;
$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Создание атрибутов" );
$this->do_add($this->obj_name, 'title', 'input', 'Название','', 50);
$this->do_add($this->obj_name, 'parent_id', 'tree_object', 'Родитель','',60 );
$this->do_add($this->obj_name, 'path_ids', 'input', 'Путь по ID');
$this->do_add($this->obj_name, 'path_titles', 'input', 'Путь по названию','',504);
$this->do_add($this->obj_name, 'level', 'int12', 'Уровень','',502);
$this->do_add($this->obj_name, '_sys_unvisible', 'checkbox', 'Невидимый','', 999);
_redirect('?cat=' .$cat->cat .'&obj_name='.$this->obj_name);
}
function _on_save_object() {
global $core_db, $cat, $auth;
$attrs = array( 'attr_type', 'attr_templ', 'attr_desc', 'attr_hide', 'attr_mand', 'attr_order', '_sys_deleted' );
$obj = $this->_obj[$this->obj_name];
$sys_obj = false;
if ( ( strpos( $this->obj_name, '_sys_') !== false ) ) {
$sys_obj = true;
}
// Вычисляем текущие хеши, чтобы понять, есть ли изменения в данных
$oldObjHash = [];
$db2 = $core_db->q( 'SELECT * FROM `_sys_datatypes` WHERE `obj_name` = "' . $this->obj_name . '" ORDER BY `attr_order`' );
while( $db2->r() ) {
$attr_hash_array = [];
foreach ($attrs as $k ) {
$attr_hash_array[$k] = $db2->f($k);
}
$oldObjHash[$db2->f('attr_name')] = md5(json_encode($attr_hash_array));
}
$sql = "SELECT TABLE_COMMENT FROM `information_schema`.`TABLES` where TABLE_SCHEMA = '".$core_db->dbname."' and TABLE_NAME = '".$this->obj_name."' ";
$db2 = $core_db->q($sql);
$db2->nr();
$oldObjTitle = $db2->f('TABLE_COMMENT');
foreach ( $obj as $attr_name => $attr_vals ) {
$presave = [];
foreach ($attrs as $k ) {
if (isset( $attr_vals[$k])) {
$presave[$k] = $attr_vals[$k];
} else {
$presave[$k] = "0";
}
}
$attr_hash = md5(json_encode($presave));
$presave['obj_name'] = $this->obj_name;
$presave['attr_name'] = $attr_name;
if ($attr_hash != $oldObjHash[$attr_name]) {
$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Изменение атрибута " . $attr_name );
$sql = 'REPLACE INTO `_sys_datatypes` (`' . implode('`, `',array_keys($presave)) . '`) VALUES ("'.implode('" , "',array_values($presave)) . '")';
$core_db->q( $sql );
$this->sLog( $sql );
}
}
if ($oldObjTitle != $this->obj_title) {
$sql = "ALTER TABLE `".$this->obj_name."` COMMENT = '".db_escape_string($this->obj_title)."';";
$core_db->q( $sql );
$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Изменение комментария " . $this->obj_name );
$this->sLog( $sql );
}
_redirect('?cat=' .$cat->cat .'&obj_name='.$this->obj_name);
}
function sLog( $txt = '' ) {
$f = fopen( _ENGINE_DIR . 'migrations/' . $this->migrationPrefix . '-' . $this->obj_name . ".sql", "a" );
fputs($f, $txt . ";\n" );
fclose($f);
$this->saveMigration($this->migrationPrefix . '-' . $this->obj_name . ".sql");
}
function _on_del_attr() {
global $core_db, $cat;
$obj_name = $this->obj_name;
$attr_name = $this->attr_name;
if ( $obj_name && $attr_name ) {
$this->sLog( "-- [" . date('Y-m-d H:i:s') . "] Удаление атрибута " . $attr_name );
$core_db->q("DELETE FROM `_sys_datatypes` WHERE `obj_name` = '".$obj_name."' AND `attr_name` = '".$attr_name."'");
$this->sLog("DELETE FROM `_sys_datatypes` WHERE `obj_name` = '".$obj_name."' AND `attr_name` = '".$attr_name."'");
$core_db->q("ALTER TABLE `".$obj_name."` DROP `".$attr_name."`");
$this->sLog("ALTER TABLE `".$obj_name."` DROP `".$attr_name."`");
}
_redirect('?cat=' . $cat->cat . '&obj_name='. $obj_name);
}
function _on_export() {
global $cat, $core_db;
$objname = $this->obj_name;
$sql = "SHOW CREATE TABLE `".$objname."`";
$db2 = $core_db->q($sql);
$db2->nr();
$sql_arr[] = $db2->f('Create Table');
$sql = "SELECT * FROM `_sys_datatypes` WHERE `obj_name` = '".$objname."'";
$db2 = $core_db->q($sql);
while( $db2->nr() ) {
$sql_arr[] = "REPLACE INTO `_sys_datatypes`
(`obj_name`,`attr_name`,`attr_type`,`attr_templ`,`attr_desc`,`attr_hide`,`attr_mand`,`attr_order`)
VALUES
(
'".db_escape_string($db2->f('obj_name'))."',
'".db_escape_string($db2->f('attr_name'))."',
'".db_escape_string($db2->f('attr_type'))."',
'".db_escape_string($db2->f('attr_templ'))."',
'".db_escape_string($db2->f('attr_desc'))."',
'".db_escape_string($db2->f('attr_hide'))."',
'".db_escape_string($db2->f('attr_mand'))."',
'".db_escape_string($db2->f('attr_order'))."'
)
";
}
$html .= implode($sql_arr, ';<br>');
echo $html;
die();
}
function _on_export_grp() {
global $core_db;
foreach( $this->obj_names as $objname ) {
$sql = "SHOW CREATE TABLE `".$objname."`";
$db2 = $core_db->q($sql);
$db2->nr();
$sql_arr[] = $db2->f('Create Table');
$sql = "SELECT * FROM `_sys_datatypes` WHERE `obj_name` = '".$objname."'";
$db2 = $core_db->q($sql);
while( $db2->nr() ) {
$sql_arr[] = "REPLACE INTO `_sys_datatypes`
(`obj_name`,`attr_name`,`attr_type`,`attr_templ`,`attr_desc`,`attr_hide`,`attr_mand`,`attr_order`)
VALUES
(
'".db_escape_string($db2->f('obj_name'))."',
'".db_escape_string($db2->f('attr_name'))."',
'".db_escape_string($db2->f('attr_type'))."',
'".db_escape_string($db2->f('attr_templ'))."',
'".db_escape_string($db2->f('attr_desc'))."',
'".db_escape_string($db2->f('attr_hide'))."',
'".db_escape_string($db2->f('attr_mand'))."',
'".db_escape_string($db2->f('attr_order'))."')
";
}
}
header('Content-Disposition: attachment; filename=dump.sql');
$html .= implode($sql_arr, ';' . PHP_EOL);
echo $html;
die();
}
function saveMigration($filename) {
global $core_db;
$core_db->q('SELECT apply_datetime FROM _sys_db_migrations WHERE `filename` = "'.db_escape_string($filename).'" ');
if (!$core_db->nr()) {
$core_db->q('INSERT INTO _sys_db_migrations (`filename`,`apply_datetime`) values ("'.db_escape_string($filename).'", "'.date('Y-m-d H:i:s').'" ) ');
}
}
}
?>

View File

@ -0,0 +1,102 @@
<?php
class admin_tree extends module {
var $templ = "admin_tree.htm";
var $_get_vars = array( 'act', 'parentId', 'id' );
var $_loc_vars = array('templ', 'obj_name');
var $obj_name = '';
function _on_() {
global $R, $db;
$tpl = $R->getTpl( $this->templ, 'body' );
$tmp = $this->r_subtree( 0 );
$tpl = $R->parse( 'rows', $tmp, $tpl );
$tpl = $R->set( 'form', '', $tpl );
return $R->clear( $tpl );
}
function _on_edit() {
global $R, $cat;
$tpl = $R->getTpl( $this->templ, 'body' );
$obj = new cobject ($this->obj_name);
if (!$this->id && $this->parentId ) {
$obj->set('parent_id', $this->parentId );
} else {
$obj->byId( $this->id );
}
$form = new form( $obj );
$tpl = $R->set( 'form', $form->render(), $tpl );
$tmp = $this->r_subtree( '' );
$tpl = $R->parse( 'rows', $tmp, $tpl );
return $R->clear( $tpl );
}
function _on_save_edit() {
global $cat;
$obj = new cobject($this->obj_name);
$obj->lPost();
$obj->save();
$this->reindex(0);
_redirect("?cat=" . $cat->cat . '&act=edit&id='.$obj->id);
}
function r_subtree( $id, $level = 1 ) {
global $R, $core_db;
$tpl = $R->getTpl( $this->templ, 'row' );
$tplu = $R->getTpl( $this->templ, 'row_unvisible' );
$tpls = $R->getTpl( $this->templ, 'sep' );
$obj = new cobject( $this->obj_name );
$db2 = $core_db->q( $obj->getSelect( ' AND `parent_id` = "'.$id.'" ORDER BY `title` ') );
while ( $db2->r() ) {
$obj->lRow( $db2 );
if ($obj->get('_sys_unvisible')) {
$tt = $obj->assign( $tplu );
} else {
$tt = $obj->assign( $tpl );
}
for( $i=0; $i<$level; $i++ ) {
$tt = $R->parse( 'seps', $tpls, $tt );
}
$tmp = $this->r_subtree($db2->f('id'), ($level+1));
$out .= $R->parse( 'subrows', $tmp, $tt );
}
return $out;
}
function reindex($id, $level = 1) {
global $core_db;
$obj = new cobject( $this->obj_name );
$pobj = new cobject( $this->obj_name );
$parr_ids = array();
if ( $id ) {
$pobj->byId($id);
$parr_ids = explode(',', $pobj->get('path_ids'));
$parr_titles = explode('>', $pobj->get('path_titles'));
}
$db2 = $core_db->q( $obj->getSelect( ' AND `parent_id` = "'.$id.'" ') );
while ( $db2->r() ) {
$obj->lRow( $db2 );
$parr_ids_tmp = $parr_ids;
$parr_ids_tmp[] = $db2->f('id');
$parr_titles_tmp = $parr_titles;
$parr_titles_tmp[] = $db2->f('title');
$obj->set('path_ids', implode(',', $parr_ids_tmp));
$obj->set('path_titles', implode(' > ', $parr_titles_tmp));
$obj->set('level', $level);
$obj->save();
$this->reindex($db2->f('id'), ($level+1));
}
}
}
?>

View File

@ -0,0 +1,15 @@
<?php
class auto_title extends module {
var $_loc_vars = array( 'templ' );
function _on_() {
global $cat;
return implode(" / ", $cat->path_name);
}
}
?>

View File

@ -0,0 +1,57 @@
<?php
class line_menu extends module {
var $templ = "menu.htm";
var $_loc_vars = array( 'templ', 'root', 'noexit' );
var $obj;
function _on_() {
global $R, $core_db, $cat;
$tpl = $R->getTpl( $this->templ, 'body' );
$tpli = $R->getTpl( $this->templ, 'item' );
$tplis = $R->getTpl( $this->templ, 'item_sel' );
$tplsep = $R->getTpl( $this->templ, 'sep' );
if (!$this->root ) $this->root = $cat->cat;
$this->obj = new cobject(__REAL_CAT_OBJ_);
$sql_where = '';
if ($this->noexit) {
$sql_where = ' AND id not in (18) ';
global $auth;
if ($auth->is_login) {
$tpl = $R->set('current_user_name', $auth->user_obj->assign('{name}'), $tpl);
}
}
$tpl = $R->set('root', 'root'.crc32($this->root), $tpl);
$db2 = $core_db->q( $this->obj->getSelect(' AND `cat_id` = "'.db_escape_string($this->root).'"') );
if ($db2->nr() ) {
$this->obj->lRow($db2);
$tpl = $this->obj->assign($tpl);
}
$db2 = $core_db->q( $this->obj->getSelect( ' AND `parent_cat` = "' . $this->root . '" AND `_sys_unvisible` = "0" '.$sql_where.' ORDER BY `_sys_order`') );
$first = true;
while ( $db2->r() ) {
$this->obj->lRow( $db2 );
if ( !in_array($db2->f('cat_id'), $cat->path) ) {
$tt = $this->obj->assign( $tpli );
} else {
$tt = $this->obj->assign( $tplis );
}
if ( $first ) $first = false;
else
$tpl = $R->parse( 'menu_item', $tplsep, $tpl );
$tpl = $R->parse( 'menu_item', $tt, $tpl );
}
return $R->clear( $tpl );
}
}
?>

View File

@ -0,0 +1,65 @@
<?php
class loginbox extends module {
var $_loc_vars = array( 'templ' );
var $_post_vars = array( 'login', 'passwd', 'logout' );
var $templ = 'loginbox.htm';
var $error = '';
function _on_() {
global $auth;
if ( $auth->is_login() ) {
if ( $this->logout ) {
$auth->do_logout();
_redirect('');
} else {
return $this->is_login();
}
}
else {
if ( $this->login ) {
$this->checkAuth();
}
return $this->r_form();
}
}
function r_form() {
global $R;
$tpl = $R->getTpl( $this->templ, 'form' );
if ( $this->error ){
$tpl = $R->set( 'err_msg', $this->error.'<br>', $tpl );
}
return $R->clear( $tpl );
}
function is_login() {
global $auth, $R;
$tpl = $R->getTpl( $this->templ, 'islogin' );
$tpl = $auth->user_obj->assign( $tpl );
return $R->clear( $tpl );
}
function checkAuth() {
global $core_db, $auth;
if (!$this->passwd ) {
$this->error = 'Не указан пароль!';
return;
} else {
$db2 = $core_db->q( 'SELECT `id` FROM `_sys_users` WHERE LOWER(`login`) = "'.strtolower($this->login).'" AND `passwd` = MD5("'.$this->passwd.'") AND !`_sys_deleted`' );
if ( $db2->r() ) {
$auth->do_login( $db2->f('id') );
_redirect('');
} else {
$this->error = 'Авторизация неверна';
return;
}
}
}
}
?>

View File

@ -0,0 +1,113 @@
<?php
class object_admin extends module {
var $_loc_vars = array( 'templ', 'obj_name', 'del', 'add','onPage' );
var $_get_vars = array( 'act', 'id' );
var $obj;
var $templ = 'object_admin.htm';
var $del = true;
var $add = true;
var $onPage=10;
function _init() {
$this->obj = new cobject( $this->obj_name );
return parent::_init();
}
function _on_() {
global $R;
$db = $this->obj->getDB();
$tpl = $R->getTpl( $this->templ, 'body' );
$tplr = $R->getTpl( $this->templ, 'row' );
$tpltd = $R->getTpl( $this->templ, 'td' );
$tplth = $R->getTpl( $this->templ, 'th' );
$tpl_del_td = $R->getTpl( $this->templ, 'del_td' );
$tpl_del_th = $R->getTpl( $this->templ, 'del_th' );
foreach( $this->obj->attrs as $attr_name => $attrs ) {
if ( $attrs['hide'] ) continue;
$tt = $R->set('attr_name', $attrs['desc'], $tplth );
$tpl = $R->parse( 'head_cols', $tt, $tpl );
$tt = $R->set('attr_name', $attr_name, $tpltd );
$tplr = $R->parse( 'row_cols', $tt, $tplr);
}
if ( $this->del ) {
$tpl = $R->parse( 'head_cols', $tpl_del_th, $tpl );
$tplr = $R->parse( 'row_cols', $tpl_del_td, $tplr);
}
$filter = new filter( $this->obj_name );
$filter->parse();
$db2 = $db->q( $this->obj->getSelectEx( 'COUNT(*) as `cnt`', $filter->getSQL() ) );
$db2->r();
$size = $db2->f('cnt');
$pw = new Walker( $size, $this->onPage );
$tpl = $R->set( 'filter', $filter->getHTML() , $tpl);
$db2 = $db->q( $this->obj->getSelect( $filter->getSQL() . ' ORDER BY `ID` DESC ' . $pw->getSQL() ) );
while( $db2->r() ) {
$this->obj->lRow($db2);
$tt = $this->obj->assign( $tplr, true );
$tpl = $R->parse( 'rows', $tt, $tpl );
}
$this->obj->byId($this->id);
if ( !$this->id && !$this->add ) {
$tpl = $R->set( 'form', '' , $tpl);
} else {
$tpl = $R->set( 'form', $this->r_form() , $tpl);
}
$tpl = $R->set( 'walker', $pw->getHTML() , $tpl);
$tpl = $R->set( 'cur_page', $pw->page, $tpl );
$tpl = $R->set( 'filter_url', $this->_get_filter_url(), $tpl );
return $R->clear( $tpl );
}
function r_form() {
$form = new form( $this->obj );
return $form->render();
}
function _on_save_edit() {
global $cat;
if ( !$this->id && !$this->add ) _redirect('?cat=' . $cat->cat );
$this->obj->lPost();
if ( $this->obj->validate() ) {
$this->obj->save();
} else {
return $this->r_form();
}
_redirect('?cat=' . $cat->cat . '&' . $this->_get_filter_url() .'&curpage='.$_GET['curpage'] );
}
function _on_del() {
global $cat;
if ( $this->del ) {
$this->obj->byId( $this->id );
$this->obj->del();
}
_redirect('?cat=' . $cat->cat . '&' . $this->_get_filter_url() .'&curpage='.$_GET['curpage']);
}
function _get_filter_url() {
foreach( $_GET as $k => $v ) {
if ( strpos($k, $this->obj_name.'_') === 0 ) {
$ret = '&'.$k.'='.$v;
}
}
return $ret;
}
}
?>

View File

@ -0,0 +1,58 @@
<?php
class object_polygon_view extends module {
public $_loc_vars = [ 'templ', 'obj_name' ];
public $_get_vars = [ 'act', 'id' ];
public $obj;
public $templ = 'object_polygon_view.htm';
public $onPage = 20;
public $nofilter = 0;
public function _init() {
$this->obj = new cobject($this->obj_name);
return parent::_init();
}
public function _on_() {
global $R, $db, $core_db;
$tpl = $R->getTpl($this->templ, 'body');
$tplr = $R->getTpl($this->templ, 'row');
$db2 = $this->obj->getDB()->q($this->obj->getSelectEx('id, title, color, ASTEXT(`geom`) as `geom` '));
while($db2->nr()) {
$tt = $tplr;
$coords = $this->mysql2json($db2->f('geom'));
$tt = $R->set('coords', $coords, $tt);
$tt = $R->set('id', $db2->f('id'), $tt);
$tt = $R->set('title', htmlspecialchars_decode($db2->f('title')), $tt);
$tt = $R->set('color', $db2->f('color') ? $db2->f('color') : '#00FF00', $tt);
$tpl = $R->parse('rows', $tt, $tpl);
}
return $R->clear($tpl);
}
public function mysql2json($str) {
// POLYGON((59.94778267548529 30.047386140625,60.12503918773836 30.468986482421876,59.92986664045532 30.963371248046883,59.84083181279909 30.456626863281247,59.960180395813275 30.38933560351563,59.94778267548529 30.047386140625))
preg_match_all('/POLYGON\(\((.*?)\)\)/', $str, $arr);
$points = explode(',', $arr[1][0]);
foreach($points as $point) {
$ret[0][] = explode(' ', $point);
}
return json_encode($ret);
}
}
?>

View File

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html style="height: 100%;">
<head>
<title>{autotitle}</title>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="format-detection" content="telephone=no">
<base href="{_SITE_ROOT_}">
{include:include/_static_css_headers.htm}
{include:include/_static_js_headers.htm}
{add_headers}
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-secondary justify-content-between p-1 p-lg-0" id="menu">
{top_menu}
</nav>
<nav class="navbar navbar-expand-lg navbar-light bg-secondary justify-content-between small p-1 p-lg-0 border-top">
{top_sub_menu}
</nav>
<div class="pt-3 pb-5">
{body}
</div>
<div style="display: none;" id="msgbox"></div>
<div id="blackout_sbmt" class="w-100 h-100 justify-content-center" style="position: fixed; top:0; left:0; background: #222222aa; display: none; z-index: 9999;">
<div style="width: 200px; height: 200px; align-self: center; text-align: center; color: white;"><img src="assets/img/gears.gif"><br><span id="blackoutText">Загружаю...</span></div>
</div>
</body>
</html>

View File

@ -0,0 +1,46 @@
#[body]#
<div class="container">
<h1>{cur_cat_name}</h1>
<div class="row">
<div class="col-12 col-lg-4">
<div class="p-2 bg-white">
<h2 class="px-3 pt-2">Дерево</h2>
<hr/>
<div class="px-2">
<b>Корень</b><br>
{rows}
</div>
</div>
</div>
<div class="col-12 col-lg-8">
<div class="p-2 bg-light h-100">
<h2 class="px-3 pt-2">Параметры категории</h2>
<hr/>
<div>
{form}
</div>
</div>
</div>
</div>
</div>
<script>
$('#module').change(function() {
$.get('?cat={cur_cat}&act=getVars&mname=' + $('#module').val(), function(data) {
$('#for_vals').html(data);
});
});
$('#module').parent().append( '<div id="for_vals" class="alert alert-light text-primary p-1 small mt-1 text-monospace"></div>' );
</script>
#[!body]#
#[row]#
{seps}|-- <a href="?cat={cur_cat}&act=edit&id={id}" title="{access_group}">{cat_name}</a> [<a href="?cat={cur_cat}&act=edit&parentCat={cat_id}" title="Подкатегория">+</a>]<br>
{subrows}
#[!row]#
#[sep]#
&nbsp;&nbsp;
#[!sep]#
#[row_unvisible]#
{seps}|--<a href="?cat={cur_cat}&act=edit&id={id}"><span style="color: #aaa;">{cat_name}</span></a> [<a href="?cat={cur_cat}&act=edit&parentCat={cat_id}" title="Подкатегория">+</a>]<br>
{subrows}
#[!row_unvisible]#

View File

@ -0,0 +1,26 @@
#[body]#
<div class="container-fluid">
<h2>{cur_cat_name}</h2>
<div>
{menu_item}
</div>
</div>
#[!body]#
#[item]#
<div align="center" style="width: 150px; height: 100px; float: left; margin: 10px;">
<a href="?cat={cat_id}">
<img src="{icon}" style="height: 48px; width: 48px;"><br>
{cat_name}
</a><br>
</div>
#[!item]#
#[item_sel]#
<div align="center" style="width: 150px; float: left; margin: 10px;">
<a href="?cat={cat_id}">
<img src="{icon}" style="height: 48px; width: 48px;"><br>
{cat_name}
</a><br>
</div>
#[!item_sel]#
#[sep]#
#[!sep]#

View File

@ -0,0 +1,46 @@
#[body]#
<div class="container">
<h1>{cur_cat_name}</h1>
<div class="row">
<div class="col-12 col-lg-4">
<div class="p-2 bg-white">
<h2 class="px-3 pt-2">Дерево</h2>
<hr/>
<div class="px-2">
<b>Корень</b><br>
{rows}
</div>
</div>
</div>
<div class="col-12 col-lg-8">
<div class="p-2 bg-light h-100">
<h2 class="px-3 pt-2">Параметры категории</h2>
<hr/>
<div>
{form}
</div>
</div>
</div>
</div>
</div>
<script>
$('#module').change(function() {
$.get('?cat={cur_cat}&act=getVars&mname=' + $('#module').val(), function(data) {
$('#for_vals').html(data);
});
});
$('#module').parent().append( '<div id="for_vals" class="alert alert-light text-primary p-1 small mt-1 text-monospace"></div>' );
</script>
#[!body]#
#[row]#
{seps}|--<img src="{icon}" style="height: 16px;"> <a href="?cat={cur_cat}&act=edit&id={id}" title="{access_group}">{cat_name}</a> [<a href="?cat={cur_cat}&act=edit&parentCat={cat_id}" title="Подкатегория">+</a>]<br>
{subrows}
#[!row]#
#[sep]#
&nbsp;&nbsp;
#[!sep]#
#[row_unvisible]#
{seps}|--<img src="{icon}" style="height: 16px;"> <a href="?cat={cur_cat}&act=edit&id={id}"><span style="color: #aaa;">{cat_name}</span></a> [<a href="?cat={cur_cat}&act=edit&parentCat={cat_id}" title="Подкатегория">+</a>]<br>
{subrows}
#[!row_unvisible]#

View File

@ -0,0 +1,100 @@
#[body]#
<style type="text/css">
tr.unvis_1 > td {
color: #6c757d !important;
}
tr.unvis_1 {
opacity: .6;
}
</style>
<div class="container-fluid">
<div class="row">
<div class="col-12 col-lg-6 col-xl-8" id="colTable">
<div class="bg-white rounded p-2">
<h2>{obj_name} <span class="small text-muted">{obj_title}</span></h2>
<button class="btn btn-secondary btn-sm" type="button" data-toggle="collapse" data-target="#pageFilter" aria-expanded="false" aria-controls="multiCollapseExample2"><i class="far fa-filter"></i> Фильтр</button>
<div class="q_filter collapse bg-light p-2 mt-2" id="pageFilter">
{filter}
</div>
<div class="table-responsive mt-3">
<table class="table table-sm small table-hover">
<tr><th style="width: 50px;"></th><th>ID</th>{head_cols}{del_h}</tr>
{rows}
</table>
</div>
{walker}
</div>
</div>
<div class="col-12 col-lg-6 col-xl-4" id="colForm" data-maximaze="false">
<a name="form"></a>
<div class="sticky-top">
<div class="row">
<div class="col-10">
<h3>Редактирование объекта [id: {id}] <a href="?cat={cur_cat}&obj_name={obj_name}"><i class="fas fa-sync"></i></a></h3>
</div>
<div class="col-2 text-right">
<a href="javascript:switchMax();"><i class="fas fa-arrows-h"></i></a>
</div>
</div>
<div class="bg-light p-2 form-sm small">
{form}
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
function switchMax() {
var is_max = $('#colForm').data('maximaze');
if (is_max == false ) {
$('#colForm').removeClass('col-lg-6');
$('#colForm').removeClass('col-xl-4');
$('#colForm').addClass('col-lg-10');
$('#colTable').removeClass('col-lg-6');
$('#colTable').removeClass('col-xl-8');
$('#colTable').addClass('col-lg-2');
$('#colForm').data('maximaze', true);
} else {
$('#colForm').data('maximaze', false);
$('#colForm').addClass('col-lg-6');
$('#colForm').addClass('col-xl-4');
$('#colForm').removeClass('col-lg-10');
$('#colTable').addClass('col-lg-6');
$('#colTable').addClass('col-xl-8');
$('#colTable').removeClass('col-lg-2');
}
}
</script>
#[!body]#
#[del_th]#
<th style="width: 25px;">Уд.</th>
#[!del_th]#
#[del_td]#
<td><a href="?cat={cur_cat}&act=del&id={id}&obj_name={obj_name}&curpage={cur_page}{filter_url}" onClick="return confirm('Удалить?');" title="Удалить"><i class="fas text-danger fa-times"></i></a></td>
#[!del_td]#
#[th]#
<th>{attr_name}</th>
#[!th]#
#[td]#
<td>{{attr_name}}</td>
#[!td]#
#[row]#
<tr class="unvis_{_sys_unvisible_real}"><td class="text-nowrap">
<a href="?cat={cur_cat}&id={id}&obj_name={obj_name}&curpage={cur_page}{filter_url}" class="mr-2" title="Edit"><i class="fas fa-edit"></i></a>
<a href="?cat={cur_cat}&act=copy&id={id}&obj_name={obj_name}&curpage={cur_page}{filter_url}" onClick="return confirm('Копировать объект?');" title="Copy"><i class="fas fa-copy"></i></a>
</td>
<td>
{id}</td>{row_cols}</tr>
#[!row]#

View File

@ -0,0 +1,131 @@
#[body]#
<div class="container-fluid">
<div class="row">
<div class="col-12 col-lg-3">
<div class="p-2 bg-white">
<label>Создать объект</label>
<form method="GET">
<input name="obj_name" autocomplete="off" class="form-control" value="">
<input type="hidden" name="cat" value="{cur_cat}">
</form>
<hr/>
<label>Объекты</label>
<form method="POST">
<input type="hidden" name="cat" value="{cur_cat}"/>
<input type="hidden" name="act" value="export_grp"/>
<div>
{rows}
</div>
<input type="submit" name="submit" value="Экспорт" class="btn btn-lg btn-primary mt-3 w-100">
</form>
</div>
</div>
<div class="col-12 col-lg-9">
<div class="px-2 py-2 bg-light h-100">
<h3 class="pt-2 px-2">Атрибуты</h3>
<hr/>
<div>
{form}
</div>
</div>
</div>
</div>
</div>
#[!body]#
#[row]#
<div class="pb-0">
<div class="form-check form-check-inline mr-0">
<input class="form-check-input" type="checkbox" name="obj_names[]" value="{obj_name}">
</div>
<a href="?cat=core_object_admin&obj_name={obj_name}"><i class="far fa-edit"></i></a>
<a href="?cat={cur_cat}&obj_name={obj_name}">{obj_name}</a>
</div>
#[!row]#
#[edit_table]#
<form method="POST">
<h1><a href="?cat=core_object_admin&obj_name={obj_name}"><i class="far fa-edit"></i></a> {obj_name}</h1>
<input type="text" name="obj_title" value="{obj_title}" autocomplete="off" class="form-control form-control-sm" placeholder="Описание объекта">
<hr/>
<div class="table-responsive bg-white rounded mb-2">
<table class="table table-sm small">
<thead>
<tr>
<th>Имя</th>
<th style="min-width: 100px;">Название</th>
<th style="min-width: 200px;">Тип</th>
<th style="min-width: 100px;">Шаблон</th>
<th class="text-center">Скрыть</th>
<th class="text-center">Обязат</th>
<th class="text-center">Порядок</th>
<th></th>
</tr>
</thead>
{rows}
</table>
</div>
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="save_object">
<input type="submit" class="btn btn-primary" value="Сохранить" name="submit">
</form>
<div class="row mt-4">
<div class="col-12 col-md-6 col-lg-8 mb-3">
<div class="bg-white p-2 rounded">
<form method="POST">
<h5 class="mb-3">Новый атрибут</h5>
<div class="form-group">
<label>Имя</label>
<input name="attr_name" value="" class="form-control">
</div>
<div class="form-group">
<label>Тип</label>
<select class="form-control chosen" name="attr_type">{attr_view}</select>
</div>
<div class="form-group mb-0">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="add_attr">
<input type="hidden" name="obj_name" value="{obj_name}">
<input type="submit" value="Создать" class="btn btn-primary" name="submitbtn">
</div>
</form>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4">
<div class="bg-white p-2 rounded">
<h5 class="mb-3">Утилиты</h5>
<ul class="list-unstyled">
<li><i class="fas fa-fw fa-link"></i> <a href="?cat={cur_cat}&act=do_urled&obj_name={obj_name}">Шаблон объекта - с URL</a></li>
<li><i class="fas fa-fw fa-folder-tree"></i> <a href="?cat={cur_cat}&act=do_treeobj&obj_name={obj_name}">Шаблон объекта - дерево</a></li>
<li><i class="far fa-fw fa-file-export"></i> <a href="?cat={cur_cat}&act=export&obj_name={obj_name}">Экспорт схемы</a><br></li>
</ul>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('select.chosen').chosen({width: "100%"});
});
</script>
#[!edit_table]#
#[edit_table_row]#
<tr>
<td class="align-middle font-weight-bold">{name}</td>
<td><input class="form-control form-control-sm" name="_obj[{obj_name}][{name}][attr_desc]" value="{attr_desc}"></td>
<td><select class="form-control form-control-sm" name="_obj[{obj_name}][{name}][attr_type]">{attr_view}</select></td>
<td><input class="form-control form-control-sm" name="_obj[{obj_name}][{name}][attr_templ]" value="{attr_templ}"></td>
<td class="align-middle text-center">
<div class="custom-control custom-switch">
<input id="{name}_attr_hide" class="custom-control-input" name="_obj[{obj_name}][{name}][attr_hide]" type="checkbox" value="1" {attr_hide}>
<label class="custom-control-label" for="{name}_attr_hide"></label>
</div>
</td>
<td class="align-middle text-center">
<div class="custom-control custom-switch">
<input id="{name}_attr_mand" class="custom-control-input" name="_obj[{obj_name}][{name}][attr_mand]" type="checkbox" value="1" {attr_mand}>
<label class="custom-control-label" for="{name}_attr_mand"></label>
</div>
</td>
<td><input class="form-control form-control-sm" name="_obj[{obj_name}][{name}][attr_order]" value="{attr_order}" size="2"></td>
<td class="align-middle text-center"><a title="Удалить" onClick="return confirm('Точно удалить?');" href="?cat={cur_cat}&act=del_attr&obj_name={obj_name}&attr_name={name}"><i class="fas fa-times"></i></a></td>
</tr>
#[!edit_table_row]#

View File

@ -0,0 +1,18 @@
#[body]#
<a class="navbar-brand d-lg-none px-2" href="?cat={cat_id}">{cat_name}</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#{root}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse bg-secondary autosize-menu" id="{root}">
<ul class="navbar-nav mr-auto flex-wrap">
{menu_item}
</ul>
</div>
#[!body]#
#[item]#
<li class="nav-item"><a class="nav-link text-truncate bg-secondary align-middle px-2 text-primary" href="?cat={cat_id}"><img src="{icon}" style="height: 13px; width: 13px;top: -3px; position: relative;"> {cat_name} <span class="badge badge-primary"></span></a></li>
#[!item]#
#[item_sel]#
<li class="nav-item active"><a class="nav-link text-truncate bg-grey px-2 text-primary" href="?cat={cat_id}"><img src="{icon}" style="height: 13px; width: 13px;top: -3px; position: relative;"> {cat_name} <span class="badge badge-primary"></span></a></li>
#[!item_sel]#
#[sep]##[!sep]#

View File

@ -0,0 +1,25 @@
#[body]#
<span class="navbar-brand mx-2 py-0 align-self-start"><img src="assets/img/admin_logo.png" height="22" width="22"><span class="d-lg-none align-middle">{_SITE_TITLE_}</span></span>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#{root}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse bg-secondary autosize-menu" id="{root}">
<ul class="navbar-nav mr-auto flex-wrap">
{menu_item}
</ul>
<div class="dropdown align-self-start">
<a class="nav-link text-nowrap text-right bg-secondary align-self-baseline px-2 text-primary dropdown-toggle" data-toggle="dropdown" href="#">{current_user_name}</a>
<div class="dropdown-menu dropdown-menu-right small">
<a class="dropdown-item" href="?cat=admin_exit">Выйти</a>
</div>
</div>
</div>
#[!body]#
#[item]#
<li class="nav-item"><a class="nav-link text-truncate bg-secondary align-middle px-2 text-primary" href="?cat={cat_id}"><img src="{icon}" style="height: 13px; width: 13px;top: -3px; position: relative;"> {cat_name} <span class="badge badge-primary"></span></a></li>
#[!item]#
#[item_sel]#
<li class="nav-item active"><a class="nav-link text-truncate bg-grey px-2 text-primary" href="?cat={cat_id}"><img src="{icon}" style="height: 13px; width: 13px;top: -3px; position: relative;"> {cat_name} <span class="badge badge-primary"></span></a></li>
#[!item_sel]#
#[sep]##[!sep]#

View File

@ -0,0 +1,43 @@
#[body]#
<div class="container">
<h1>{cur_cat_name}</h1>
<div class="row">
<div class="col-12 col-lg-4">
<div class="p-2 bg-white">
<h2 class="px-3 pt-2">Дерево</h2>
<hr/>
<div class="px-2">
<b>Корень</b> [<a href="?cat={cur_cat}&act=edit&parentCat={id}" title="Подкатегория">+</a>]<br>
{rows}
</div>
</div>
</div>
<div class="col-12 col-lg-8">
<div class="p-2 bg-light h-100">
<h2 class="px-3 pt-2">Параметры объекта</h2>
<hr/>
<div>
{form}
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('select.form-control').chosen();
});
</script>
#[!body]#
#[row]#
{seps}|-- <a href="?cat={cur_cat}&act=edit&id={id}" title="{access_group}">{title}</a> [<a href="?cat={cur_cat}&act=edit&parentId={id}" title="Подкатегория">+</a>]<br>
{subrows}
#[!row]#
#[sep]#
&nbsp;&nbsp;
#[!sep]#
#[row_unvisible]#
{seps}|-- <a href="?cat={cur_cat}&act=edit&id={id}"><span style="color: #aaa;">{title}</span></a> [<a href="?cat={cur_cat}&act=edit&parentId={id}" title="Подкатегория">+</a>]<br>
{subrows}
#[!row_unvisible]#

View File

@ -0,0 +1,48 @@
#[body]#
<div>
<form method="POST" ENCTYPE="multipart/form-data">
{form_rows}
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label"></label>
<div class="col-12 col-md-8 col-xl-9">
<input type="submit" name="submit" class="btn btn-primary" value="Сохранить">
</div>
</div>
{hidden_attrs}
<input type="hidden" name="id" value="{id}">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="{send_act}">
</form>
</div>
#[!body]#
#[row]#
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3 text-md-right col-form-label font-weight-bold">{attr_title}{attr_mand}</label>
<div class="col-12 col-md-8 col-xl-9">
{attr_html}
<small class="text-danger">{attr_error}</small>
</div>
</div>
#[!row]#
#[mand]#
<span class="text-danger">*</span>
#[!mand]#
#[row_checkbox]#
<div class="form-group row py-1 mb-0">
<label class="col-12 col-md-4 col-xl-3"></label>
<div class="col-12 col-md-8 col-xl-9">
<div class="custom-controls-stacked2">
<div class="custom-control custom-checkbox">
{attr_html}
<label for="chbx_{attr_name}" class="custom-control-label">{attr_title}{attr_mand}</label>
</div>
<small class="text-danger">{attr_error}</small>
</div>
</div>
</div>
#[!row_checkbox]#

View File

@ -0,0 +1,24 @@
#[body]#
<span id="resp{id}{cur_cat}{send_act}">
<form method="POST" id="form{id}{cur_cat}{send_act}" onSubmit="submit_form({id}, '{id}{cur_cat}{send_act}'); return false;" ENCTYPE="multipart/form-data">
<table>
{form_rows}
<tr>
<td colspan="2">
{hidden_attrs}
<input type="hidden" name="id" value="{id}">
<input type="hidden" name="cat" value="{cur_cat}">
<input type="hidden" name="act" value="{send_act}">
<input type="submit" name="is_ajax" value="Сохранить">
</td>
</tr>
</table>
</form>
</span>
#[!body]#
#[row]#
<tr><td>{attr_title}{attr_mand}:</td><td>{attr_html}<span id="error">{attr_error}</span></td></tr>
#[!row]#
#[mand]#
<span id="error">*</span>
#[!mand]#

View File

@ -0,0 +1,10 @@
#[body]#
<ol class="breadcrumb">{rows}</ol>
#[!body]#
#[row]#
<li class="breadcrumb-item"><a href="{url}" title="{title}" alt="{title}">{title}</a></li>
#[!row]#
#[sep]##[!sep]#
#[last_row]#
<li class="breadcrumb-item active">{title}</li>
#[!last_row]#

View File

@ -0,0 +1,6 @@
<div class="inp">
{attr_title}:<br>
<textarea class="{filter_key}_val" id="{filter_key}_val" name="{filter_key}_val">
{_val}
</textarea>
</div>

View File

@ -0,0 +1,33 @@
<div class="inp">
{attr_title}: с <input autocomplete="off" type="text" class="{filter_key}_dateperiod" value="{_from}" id="{filter_key}_from" name="{filter_key}_from"> по <input autocomplete="off" value="{_to}" class="{filter_key}_dateperiod" type="text" id="{filter_key}_to" name="{filter_key}_to">
</div>
<script>
$(function() {
$('.{filter_key}_dateperiod').dateRangePicker(
{
autoClose: true,
format: 'DD.MM.YYYY',
separator : ' to ',
shortcuts :
{
'prev-days': [3,5,7],
'prev': ['week','month','year'],
'next-days':null,
'next':null
},
getValue: function()
{
if ($('#{filter_key}_from').val() && $('#{filter_key}_to').val() )
return $('#{filter_key}_from').val() + ' to ' + $('#{filter_key}_to').val();
else
return '';
},
setValue: function(s,s1,s2)
{
$('#{filter_key}_from').val(s1);
$('#{filter_key}_to').val(s2);
}
} );
});
</script>

View File

@ -0,0 +1,3 @@
<div class="inp">
{attr_title}: <input autocomplete="off" type="text" class="{filter_key}_val" value="{_val}" id="{filter_key}_val" name="{filter_key}_val">
</div>

View File

@ -0,0 +1,5 @@
<div class="inp">
{attr_title}:
<input autocomplete="off" {_checked} type="checkbox" class="{filter_key}_checked" value="1" id="{filter_key}_checked" name="{filter_key}_checked">
<input autocomplete="off" type="number" class="{filter_key}_val" value="{_val}" id="{filter_key}_val" name="{filter_key}_val">
</div>

View File

@ -0,0 +1,5 @@
<div class="inp">
{attr_title}:
<input autocomplete="off" {_checked} type="checkbox" class="{filter_key}_checked" value="1" id="{filter_key}_checked" name="{filter_key}_checked">
<input autocomplete="off" type="number" class="{filter_key}_val" value="{_val}" id="{filter_key}_val" name="{filter_key}_val">
</div>

View File

@ -0,0 +1,11 @@
<link rel="stylesheet" href="/admin/assets/css/bootstrap.css?1728913930">
<link rel="stylesheet" href="/admin/assets/css/chosen.min.css?1728913930">
<link rel="stylesheet" href="/admin/assets/css/fonts_full.css?1728913930">
<link rel="stylesheet" href="/admin/assets/css/jquery-ui.css?1728913930">
<link rel="stylesheet" href="/admin/assets/css/jquery-ui.structure.min.css?1728913930">
<link rel="stylesheet" href="/admin/assets/css/jquery-ui.theme.min.css?1728913930">
<link rel="stylesheet" href="/admin/assets/css/jquery.autocomplete.css?1728913930">
<link rel="stylesheet" href="/admin/assets/css/jquery.fancybox.min.css?1728913930">
<link rel="stylesheet" href="/admin/assets/css/jquery.periodpicker.min.css?1728913930">
<link rel="stylesheet" href="/admin/assets/css/redactor.css?1728913930">
<link rel="stylesheet" href="/admin/assets/css/custom.css?1728913930">

View File

@ -0,0 +1,15 @@
<script src="/admin/assets/js/jquery.js?1728913930"></script>
<script src="/admin/assets/js/bootstrap4.min.js?1728913930"></script>
<script src="/admin/assets/js/chosen.jquery.min.js?1728913930"></script>
<script src="/admin/assets/js/clipboard.min.js?1728913930"></script>
<script src="/admin/assets/js/jquery.fancybox.min.js?1728913930"></script>
<script src="/admin/assets/js/jquery-ui.min.js?1728913930"></script>
<script src="/admin/assets/js/jquery.autocomplete.js?1728913930"></script>
<script src="/admin/assets/js/jquery.form.js?1728913930"></script>
<script src="/admin/assets/js/jquery.input.counter.js?1728913930"></script>
<script src="/admin/assets/js/jquery.maskedinput-1.3.min.js?1728913930"></script>
<script src="/admin/assets/js/jquery.periodpicker.full.min.js?1728913930"></script>
<script src="/admin/assets/js/jquery.tablesorter.min.js?1728913930"></script>
<script src="/admin/assets/js/jquery.utils.min.js?1728913930"></script>
<script src="/admin/assets/js/redactor.js?1728913930"></script>
<script src="/admin/assets/js/bootstrap4.utils.js?1728913930"></script>

View File

@ -0,0 +1,46 @@
#[form]#
<div class="container" style="max-width: 600px;">
<div class="bg-white p-2 rounded">
<h2 class="border-bottom mb-2 pb-2">Авторизация</h2>
<form method="POST">
<div class="form-group mb-1">
<label class="small mb-0">Логин</label>
<input type="text" name="login" value="" class="form-control">
</div>
<div class="form-group">
<label class="small mb-0">Пароль</label>
<input name="passwd" type="password" value="" class="form-control">
</div>
<div class="error">{err_msg}</div>
<input name="submit" type="submit" class="btn btn-action btn-lg w-100" value="Войти">
</form>
</div>
</div>
#[!form]#
#[islogin]#
<div class="container" style="max-width: 600px;">
<div class="bg-white p-2 rounded">
<h2 class="border-bottom mb-3 pb-2">Админка Бамболо</h2>
<div class="row">
<div class="col-3">
<img src="{_STATIC_ROOT_}images/{user_photo}.jpg" class="img-fluid"/>
</div>
<div class="col-9">
<div class="text-left">
<div class="small text-muted mb-0">Имя</div>
<div>{name}</div>
<div class="small mb-0 mt-2"><span class="text-muted">Привелегии:</span> {group}</div>
</div>
</div>
<div class="col-12 mt-3">
<form method="POST">
<input name="logout" class="btn btn-action btn-lg w-100" type="submit" value="Выйти">
</form>
</div>
</div>
</div>
</div>
#[!islogin]#

View File

@ -0,0 +1,93 @@
#[body]#
<style type="text/css">
tr.unvis_1 > td {
color: #6c757d !important;
}
tr.unvis_1 {
opacity: .6;
}
</style>
<div class="container-fluid">
<div class="row">
<div class="col-12 col-lg-6 col-xl-8" id="colTable">
<div class="bg-white rounded p-2">
<h2>{cur_cat_name}</h2>
<button class="btn btn-secondary btn-sm" type="button" data-toggle="collapse" data-target="#pageFilter" aria-expanded="false" aria-controls="multiCollapseExample2"><i class="far fa-filter"></i> Фильтр</button>
<div class="q_filter collapse bg-light p-2 mt-2" id="pageFilter">
{filter}
</div>
<div class="table-responsive mt-3">
<table class="table table-sm small table-hover">
<tr><th>ID</th>{head_cols}{del_h}</tr>
{rows}
</table>
</div>
{walker}
</div>
</div>
<div class="col-12 col-lg-6 col-xl-4" id="colForm" data-maximaze="false">
<a name="form"></a>
<div class="sticky-top">
<div class="row">
<div class="col-10">
<h3>Редактирование <a href="?cat={cur_cat}"><i class="fas fa-sync"></i></a></h3>
</div>
<div class="col-2 text-right">
<a href="javascript:switchMax();"><i class="fas fa-arrows-h"></i></a>
</div>
</div>
<div class="bg-light p-2 form-sm small">
{form}
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
function switchMax() {
var is_max = $('#colForm').data('maximaze');
if (is_max == false ) {
$('#colForm').removeClass('col-lg-6');
$('#colForm').removeClass('col-xl-4');
$('#colForm').addClass('col-lg-10');
$('#colTable').removeClass('col-lg-6');
$('#colTable').removeClass('col-xl-8');
$('#colTable').addClass('col-lg-2');
$('#colForm').data('maximaze', true);
} else {
$('#colForm').data('maximaze', false);
$('#colForm').addClass('col-lg-6');
$('#colForm').addClass('col-xl-4');
$('#colForm').removeClass('col-lg-10');
$('#colTable').addClass('col-lg-6');
$('#colTable').addClass('col-xl-8');
$('#colTable').removeClass('col-lg-2');
}
}
</script>
#[!body]#
#[del_th]#
<th>Уд.</th>
#[!del_th]#
#[del_td]#
<td><a href="?cat={cur_cat}&act=del&id={id}&curpage={cur_page}{filter_url}" onClick="return confirm('Удалить?');" title="Удалить"><i class="fas fa-times text-danger "></i></a></td>
#[!del_td]#
#[th]#
<th>{attr_name}</th>
#[!th]#
#[td]#
<td>{{attr_name}}</td>
#[!td]#
#[row]#
<tr class="unvis_{_sys_unvisible_real}"><td><a href="?cat={cur_cat}&id={id}&curpage={cur_page}{filter_url}#form" title="Edit"><i class="fas fa-edit"></i></a> {id}</td>{row_cols}</tr>
#[!row]#

View File

@ -0,0 +1,86 @@
#[body]#
<input id="address" name="address" type="text" style="font-size: 20px; margin: 10px 0px;" placeholder="Поиск адреса" tabindex="0"/>
<link href="https://cdn.jsdelivr.net/npm/suggestions-jquery@19.8.0/dist/css/suggestions.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/suggestions-jquery@19.8.0/dist/js/jquery.suggestions.min.js"></script>
<script>
var mypm;
$("#address").suggestions({
token: "ccec8991a826fdb7832cc2db1be8098f8cce8759",
type: "ADDRESS",
deferRequestBy: 300,
minChars: 4,
triggerSelectOnEnter: true,
/* Вызывается, когда пользователь выбирает одну из подсказок */
onSelect: function(suggestion) {
if (mypm ) {
myMap.geoObjects.remove(mypm);
}
var lat = suggestion.data.geo_lat;
var lon = suggestion.data.geo_lon;
mypm = new ymaps.Placemark([lat,lon], {
hintContent: suggestion.unrestricted_value,
});
myMap.geoObjects.add(mypm);
myMap.setCenter([lat,lon], 16);
}
});
</script>
<script src="//api-maps.yandex.ru/2.1/?lang=ru_RU" type="text/javascript"></script>
<div id="map" style="width: 100%; height: 600px; margin-bottom: 40px;"></div>
<script>
ymaps.ready(init);
var myMap;
var poligons = new Array();
function init() {
myMap = new ymaps.Map('map', {
center: [59.939027,30.314454],
zoom: 10,
controls: ['default']
});
myMap.controls.remove('searchControl');
{rows}
}
function dosearch() {
var str = $('#addr').val();
}
</script>
#[!body]#
#[row]#
myMap.geoObjects.add(
new ymaps.GeoObject({
geometry: {
type: "Polygon",
coordinates: {coords},
fillRule: "nonZero"
},
properties:{
hintContent: "{title}",
balloonContentHeader: '{title}',
balloonContentFooter: ''
}
}, {
fillColor: '{color}',
strokeColor: '#222',
opacity: 0.6,
strokeWidth: 1,
strokeStyle: 'solid'
})
);
#[!row]#

View File

@ -0,0 +1,5 @@
#[body]#<nav class="my-4 table-responsive w-100"><ul class="pagination justify-content-md-center">{pages}</ul></nav>#[!body]#
#[num]#<li class="page-item"><a href="{url}" class="page-link">{page_num}</a></li>#[!num]#
#[num_c]#<li class="page-item active"><span class="page-link">{page_num}</span></li>#[!num_c]#
#[page_prev]#<!--li class="page-item"><a href="{url}" rel="prev" class="page-link"><i class="fas fa-chevron-left"></i></a></li-->#[!page_prev]#
#[page_next]#<li class="page-item"><a href="{url}" rel="next" class="page-link"><i class="fas fa-chevron-right"></i></a></li>#[!page_next]#

View File

@ -0,0 +1,216 @@
#[body]#
<style>
#newzoneedit {
display: none;
}
</style>
<script type="text/javascript" src="js/jquery.ajaxform.js"></script>
<script src="//api-maps.yandex.ru/2.1/?lang=ru_RU" type="text/javascript"></script>
<h2 style="text-align: center;">{cur_cat_name}</h2>
<div style="width: 100%; margin-top: 10px;">
<div id="map" style="width: 100%; height: 400px;"></div>
</div>
<script>
var myMap;
var myPolygon;
var editBtn;
var poligons = new Array();
ymaps.ready(init);
function init() {
myMap = new ymaps.Map('map', {
center: [59.939027,30.314454],
zoom: 10,
controls: ['smallMapDefaultSet']
});
editBtn = new ymaps.control.Button(
{
data: {
content: "Создать участок",
},
options: {
maxWidth: 250
}
}
);
myMap.controls.add(editBtn, {float: 'left'});
editBtn.events.add('click', function(e) {
if (!editBtn.isSelected()) {
editBtn.data.set('content', 'Завершить рисование');
drawPolygon();
} else {
editBtn.data.set('content', 'Создать участок');
stopDrawing();
}
});
{rows}
}
function drawPolygon() {
myPolygon = new ymaps.Polygon([], {}, {
editorDrawingCursor: "crosshair",
editorMaxPoints: 999,
fillColor: '#ed4543',
strokeColor: '#ed4543',
fillOpacity: 0.6,
strokeWidth: 1
});
myMap.geoObjects.add(myPolygon);
var stateMonitor = new ymaps.Monitor(myPolygon.editor.state);
stateMonitor.add("drawing", function (newValue) {
myPolygon.options.set("strokeColor", newValue ? '#FF0000' : '#0000FF');
});
myPolygon.editor.startDrawing();
myPolygon.events.add(['editorstatechange'], function(e) {
if ( e.originalEvent.originalEvent.originalEvent.newDrawing == false &&
e.originalEvent.originalEvent.originalEvent.oldDrawing == true ) {
editBtn.data.set('content', 'Создать зону');
editBtn.deselect();
stopDrawing();
}
});
}
function stopDrawing() {
var coords = myPolygon.geometry.getCoordinates();
myPolygon.editor.stopDrawing();
myMap.geoObjects.remove(myPolygon);
$.post("?cat={cur_cat}&act=editgeom&id=0",
{ geom: coords },
function(ret) {
var data = jQuery.parseJSON(ret);
console.log(data.id);
console.log(data);
if (data.id != 0 ) {
addPolygon(coords, data.id, data.title);
}
}
);
}
function addPolygon(coords, id, title) {
$.get('?cat={cur_cat}&act=getForm&id=' + id, function( data ) {
var params = jQuery.parseJSON(data);
_addPolygonHtml(coords, id, params.title, params.html, params.color);
}
);
}
function _addPolygonHtml(coords, id, title, html, fillcolor = "#00FF00") {
poligons[id] = new ymaps.GeoObject({
geometry: {
type: "Polygon",
coordinates: coords,
fillRule: "nonZero"
},
properties:{
myid: id,
balloonContentHeader: title,
balloonContent: html,
balloonContentFooter: '<a href="javascript:editPolygon('+id+');">Редактировать контур</a> | <a href="javascript:removePolygon('+id+');">Удалить зону</a>'
}
}, {
fillColor: fillcolor,
strokeColor: '#0000FF',
opacity: 0.5,
strokeWidth: 1,
strokeStyle: 'shortdash'
});
poligons[id].events.add(['editorstatechange'], function(e) {
if ( e.originalEvent.originalEvent.originalEvent.newDrawing == false &&
e.originalEvent.originalEvent.originalEvent.oldDrawing == true ) {
if ( e.originalEvent.target ) {
var id = e.originalEvent.target.properties.get('myid');
var coords = e.originalEvent.target.geometry.getCoordinates();
if (!id) stopDrawing();
$.post("?cat={cur_cat}&act=editgeom&id=" + id,
{ geom: coords },
function(ret) {
var data = jQuery.parseJSON(ret);
if (data.id != 0 ) {
addPolygon(coords, data.id, data.title);
}
}
);
}
}
}
);
myMap.geoObjects.add(poligons[id]);
}
function editPolygon(id) {
myPolygon = poligons[id];
myMap.geoObjects.add(myPolygon);
var stateMonitor = new ymaps.Monitor(myPolygon.editor.state);
stateMonitor.add("drawing", function (newValue) {
myPolygon.options.set("strokeColor", newValue ? '#FF0000' : '#0000FF');
});
myPolygon.editor.startDrawing();
}
function removePolygon(id) {
$.get('?cat={cur_cat}&act=remove&id=' + id, function(data) {
myMap.geoObjects.remove(poligons[id]);
});
}
function submit_form(id, idn) {
var options = {
success: function( response ) {
var params = jQuery.parseJSON(response);
var data = params.html;
$('#resp' + idn ).html('<span style="color: green;">Данные сохранены</span>' + data );
poligons[id].properties.set('balloonContent', data);
poligons[id].options.set('fillColor', params.color);
//console.log(poligons[id]);
}
};
$('#form' + idn).ajaxSubmit( options );
$('#resp' + idn).html("<img src='img/loader.gif'>");
return false;
}
</script>
#[!body]#
#[row]#
addPolygon({coords}, {id}, "{title}");
#[!row]#

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf8"?>
<templ filename="admin.htm" frame_filename="index_frame.htm">
<autotitle>
<auto_title/>
</autotitle>
<top_menu>
<line_menu templ='admin_top_menu_root.htm' noexit='true' root='index'/>
</top_menu>
<top_sub_menu>
<line_menu templ='admin_top_menu.htm' root='core_programmer' in_path='core_programmer'/>
<line_menu templ='admin_top_menu.htm' root='core_data' in_path='core_data'/>
<line_menu templ='admin_top_menu.htm' root='core_shopadmin' in_path='core_shopadmin'/>
<line_menu templ='admin_top_menu.htm' root='core_sklad' in_path='core_sklad'/>
<line_menu templ='admin_top_menu.htm' root='core_zakaz' in_path='core_zakaz'/>
<line_menu templ='admin_top_menu.htm' root='core_zakupka' in_path='core_zakupka'/>
<line_menu templ='admin_top_menu.htm' root='core_sklad' in_path='core_sklad'/>
<line_menu templ='admin_top_menu.htm' root='core_kassa' in_path='core_kassa'/>
<line_menu templ='admin_top_menu.htm' root='shop_cm' in_path='shop_cm'/>
<line_menu templ='admin_top_menu.htm' root='core-sip' in_path='core-sip'/>
<line_menu templ='admin_top_menu.htm' root='core-workers-time' in_path='core-workers-time'/>
<line_menu templ='admin_top_menu.htm' root='core-reports' in_path='core-reports'/>
</top_sub_menu>
</templ>

84
app/engine/bootstrap.php Normal file
View File

@ -0,0 +1,84 @@
<?php
$starttime = microtime( true );
if (!defined('_ENGINE_DIR')) {
define('_ENGINE_DIR', _PROJECT_DIR . 'engine/'); // Äčđĺęňîđč˙ ń äâčćęîé
}
const _CFG_DIR = _PROJECT_DIR . 'config/';
const _CORE_DIR = _ENGINE_DIR . 'core/';
const _VENDOR_DIR = _PROJECT_DIR . 'vendor/';
if (!defined('_SHOP_DIR')) {
define('_SHOP_DIR' , _PROJECT_DIR . 'www/');
}
const _FILES_DIR_ = _SHOP_DIR . '/files/';
const _VIDEO_DIR_ = _SHOP_DIR . '/video/';
const _IMAGE_DIR_ = _SHOP_DIR . '/images/';
$objects_cache = array();
$statistica = array();
$cached_objects = array();
$is_cli = (php_sapi_name() === 'cli');
require_once( _VENDOR_DIR . 'autoload.php' );
require_once( _CFG_DIR . 'accounts.php');
require_once( _CORE_DIR . 'utils.php');
require_once( _CORE_DIR . 'db.class.php');
require_once( _CFG_DIR . 'db.cfg.php');
require_once( _CORE_DIR . 'object.class.php');
require_once( _CORE_DIR . 'abstract/module.php');
/* load datatypes */
require_once( _CORE_DIR . 'abstract/attr.php');
$dir = dir( _CORE_DIR . 'attrs/');
if ($dir !== false ) {
while ( $file = $dir->read() ) {
if (substr( $file, -4 ) == '.php' ) {
require_once( _CORE_DIR . 'attrs/' .$file );
$classname = 'attr_' . substr( $file,0,-4 );
if ( class_exists( $classname ) ) {
$loaded_attrs[] = substr( $file,0,-4 );
}
}
}
}
// Ňîëüęî äë˙ WEB îęđóćĺíč˙
if ( $is_cli == false ) {
require_once( _ENGINE_DIR . 'rewrite.php');
/* Ŕâňîđčçŕöč˙ ŕäěčíîâ */
require_once( _CORE_DIR . 'auth.core.php');
$auth = new auth();
/* Ôîđěű */
require_once( _CORE_DIR . 'walker.core.php');
require_once( _CORE_DIR . 'form.core.php');
require_once( _CORE_DIR . 'filter.core.php');
/* render */
require_once( _CORE_DIR . 'render.core.php');
$R = new render();
require_once( _CORE_DIR . 'blade/BladeOne.php');
$blade = new BladeOne(
_BASE_DIR . '/bladetpl',
_BASE_DIR . '/bladetpl/cache',
BladeOne::MODE_AUTO
);
$blade->share('auth', $auth);
/* cat */
require_once( _CORE_DIR . 'cat.core.php');
$cat = new cat();
$blade->share('cat', $cat);
}
?>

View File

@ -0,0 +1,140 @@
<?php
/**
* Базовый класс,
* описывающий поведение стандартного атрибута
***/
abstract class attr {
var $attr_name; // Имя объекта, с которым будет связан атрибут
var $obj; // Ссылка на объект
var $sql_where; // Внутренняя переменная для ограничения выборки объекта
/**
* Возвращаем тип данных для MySQL
* @return string тип данных
*/
function getDBType() {
return "varchar(255)"; // Тип данных в MySQL для хранения значения атрибута
}
/**
* Конструтор. Передается имя атрибута и ссылка на объект, для которого он инициируется
*/
function __construct( $attr_name, $obj ) {
$this->attr_name = $attr_name;
$this->obj = $obj;
}
/**
* Вызывается при получении POST запроса с данным формы. Сохраняет данные в объект
* @return none
*/
function lPost() {
if ( ini_get('magic_quotes_gpc') ) {
$this->obj->set($this->attr_name,stripslashes($_POST[$this->attr_name]));
} else {
$this->obj->set($this->attr_name,$_POST[$this->attr_name]);
}
}
/**
* Получение текущего значения атрибута
* @return mixed текущие значение атрибута
*/
function getCurVal() {
return $this->obj->get( $this->attr_name );
}
/**
* Получение основногом параметров атрибута (обычно шаблон)
* @return mixed
*/
function getAttrTempl() {
return str_replace("]","}",str_replace("[","{",$this->obj->attrs[$this->attr_name]['templ']));
}
/**
* Получение конкретного параметра атрибута (тип, обязательность, шаблон итд)
* @param string $setting какой параметр нужно получить
* @return mixed
*/
function getAttrSetting($setting='') {
return $this->obj->attrs[$this->attr_name][$setting];
}
/**
* Метод вызывается всегда при сохранении объекта.
* Последние манипуляции с данными до сохранения в БД
* @return none
*/
function presave() {
if (!is_array($this->getCurVal()))
$this->obj->set($this->attr_name, htmlspecialchars( html_entity_decode( $this->getCurVal() ) ) );
}
/**
* Метод вызывается при валидации объекта.
* Проверяется корретность заполнения.
* Соответвуют ли данные в атрибуте ожидаемым
* @return bool прошел элемент валидацию или нет
*/
function validate() {
return true;
}
/**
* Метод для отрисовки HTML элемента управления
* @return html код элемента для страницы
*/
function render_input() {
if ($this->obj->attrs[$this->attr_name]['mand']) {
$required = ' required = "required" ';
} else {
$required = '';
}
return '<input class="form-control" id="' . $this->attr_name . '" ' . $required . ' type="text" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '">';
}
/**
* Метод для отрисовки HTML вывода в браузере
* @param boolean $crop использовать сокращённый вывод (для таблиц админки)
* @return html преобразованное значение атрибута для вывода на экран
*/
function render_text( $crop = false) {
return $this->getCurVal();
}
/**
* Сохранение SQL ограничение при фильтрации объектов. Используется далее фильтрами
* @param string $sql_where Хвост SQL запроса
*/
function setSqlWhere( $sql_where ) {
$this->sql_where = $sql_where;
}
/**
* Получаем HTML и SQL хвост для фильтрации объектов
* @param string $sql_where Хвост SQL запроса
* @return array ['html' => 'html код элемента с фильтром', 'sql'=>'SQL хвост запроса']
*/
function getFilter( $sql_where = '' ) {
return ['html'=> '', 'sql'=>''];
}
/**
* После сохранения объекта, когда уже точно есть ID
* @return none
*/
function postsave() {
}
}
?>

View File

@ -0,0 +1,75 @@
<?php
class attr {
var $attr_name;
var $obj;
var $DBType = "varchar(255)";
var $sql_where;
function getDBType() {
return "varchar(255)";
}
function __construct( $attr_name, $obj ) {
$this->attr_name = $attr_name;
$this->obj = $obj;
}
function lPost() {
if ( ini_get('magic_quotes_gpc') ) {
$this->obj->set($this->attr_name,stripslashes($_POST[$this->attr_name]));
} else {
$this->obj->set($this->attr_name,$_POST[$this->attr_name]);
}
}
function getCurVal() {
return $this->obj->get( $this->attr_name );
}
function getAttrTempl() {
return str_replace("]","}",str_replace("[","{",$this->obj->attrs[$this->attr_name]['templ']));
}
function getAttrSetting($setting='') {
return $this->obj->attrs[$this->attr_name][$setting];
}
function presave() {
if (!is_array($this->getCurVal()))
$this->obj->set($this->attr_name, htmlspecialchars( html_entity_decode( $this->getCurVal() ) ) );
}
function validate() {
}
function render_input() {
return '<input id="' . $this->attr_name . '" type="text" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '">';
}
function render_text( $crop ) {
return $this->getCurVal();
}
function setSqlWhere( $sql_where ) {
$this->sql_where = $sql_where;
}
function getFilter( $sql_where = '' ) {
$html = "<input name='".$this->obj->obj_name.'_'.$this->attr_name."'>";
return array('html'=> '', 'sql'=>'');
}
}
?>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,119 @@
<?php
class attr_LINK extends attr {
var $linked_obj;
var $lobj_name;
function __construct( $attr_name, $obj ) {
$this->attr_name = $attr_name;
$this->obj = $obj;
$full_type = $obj->attrs[$attr_name]['type'];
$arr = explode("|", $full_type);
$lobj_name = $arr[1];
if ($lobj_name == $obj->obj_name ) cdie('recursion');
$this->lobj_name = $lobj_name;
//$this->linked_obj = new cobject( $lobj_name, $this->obj->recursion_depth );
}
function getDBType() {
return "int(12)";
}
function getLinkedObj() {
if ( !$this->linked_obj ) {
$this->linked_obj = new cobject( $this->lobj_name, $this->obj->recursion_depth );
}
return $this->linked_obj;
}
function render_text( $crop = false ) {
$id = $this->getCurVal();
$out = '';
$tpl = $this->obj->attrs[$this->attr_name]['templ'];
if ( $id && $tpl) {
$this->getLinkedObj()->byId( $id );
$out = $this->getLinkedObj()->assign( $tpl );
} elseif ( $id ) {
return $id;
}
return $out;
}
function render_input() {
$db = $this->getLinkedObj()->getDB();
$db2 = $db->q( $this->getLinkedObj()->getSelect( $this->sql_where ) );
$id = $this->getCurVal();
$tpl = $this->obj->attrs[$this->attr_name]['templ'];
$out = '<select name="'.$this->attr_name.'" class="select form-control">';
if ( !$this->obj->attrs[$this->attr_name]['mand'] ) {
$out .= '<option value="0">---</option>';
}
while ( $db2->r() ) {
$this->getLinkedObj()->lRow( $db2 );
$tt = $this->getLinkedObj()->assign( $tpl );
if ( $id == $db2->f( 'id' ) ) $checked = 'selected';
else $checked = '';
$out .= '<option value="'.$db2->f( 'id' ).'" ' . $checked . '>' . $tt . '</option>';
}
$out .= '</select>';
return $out;
}
function getFilter( $sql_where = '' ) {
$db = $this->getLinkedObj()->getDB();
$fname = $this->obj->obj_name . '_' . $this->attr_name;
$uniq_ids = array();
if ( $this->obj->obj_name ) {
$db3 = $this->obj->getDB()->q( $this->obj->getSelectEx( ' DISTINCT(`'.$this->attr_name.'`) as `'.$this->attr_name.'` ', '' ) );
while ( $db3->nr() ) {
$uniq_ids[] = $db3->f($this->attr_name);
}
} else {
$uniq_ids = array();
}
if (!$_GET[$fname]) {
$tmp = array('<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'\'" selected>Все</option>');
$tmp_s = array('<a href="'._getCurl(array( $fname, 'curpage' )).'"><b>Все</b></a>');
} else {
$tmp = array('<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'\'">Все</option>');
$tmp_s = array('<a href="'._getCurl(array( $fname, 'curpage' )).'">Все</a>');
}
$db2 = $db->q( $this->getLinkedObj()->getSelect( $sql_where) );
$c = 0;
while ( $db2->r() ) {
if ( $this->obj->obj_name && !in_array( $db2->f('id'), $uniq_ids ) ) continue;
$tpl = strip_tags( $this->getAttrTempl() );
$this->getLinkedObj()->lRow($db2);
$tpl = $this->getLinkedObj()->assign($tpl, true);
if ( strlen($tpl) > 100 ) $tpl = substr($tpl,0,100) . '...';
if ($_GET[$fname] != $db2->f('id')) {
$tplh = '<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'\'" value="'.$db2->f('id').'">' .$tpl . '</option>';
$tplh_s = '<a href="'._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'">' .$tpl . '</a>';
} else {
$tplh = '<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'\'" value="'.$db2->f('id').'" selected>' . $tpl . '</option>';
$tplh_s = '<a href="'._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'"><b>' .$tpl . '</b></a>';
$ret['sql'] = " AND " . ($this->obj->obj_name?('`'.$this->obj->obj_name."`.`".$this->attr_name.'`'):($this->attr_name)) . " = '" . $db2->f('id') . "' " ;
}
$tmp[] = $tplh;
$tmp_s[] = $tplh_s;
$c++;
}
if ($c > 10 ) {
$ret['html'] = '<select class=\"form-control form-control-sm\" onChange="location.href=\''._getCurl(array( $fname, 'curpage' )).'&' . $fname .'=\'+$(this).val()">';
$ret['html'] .= implode('', $tmp);
$ret['html'] .= "</select>";
} else {
$ret['html'] .= implode(' | ', $tmp_s);
}
return $ret;
}
}
?>

View File

@ -0,0 +1,139 @@
<?php
class attr_MLINK extends attr {
var $linked_obj;
var $sql_where;
var $lobj_name;
function __construct( $attr_name, $obj ) {
$this->attr_name = $attr_name;
$this->obj = $obj;
$full_type = $obj->attrs[$attr_name]['type'];
$arr = explode("|", $full_type);
$lobj_name = $arr[1];
//if ($lobj_name == $obj->obj_name ) cdie('recursion');
$this->lobj_name = $lobj_name;
//$this->linked_obj = new cobject( $lobj_name, $this->obj->recursion_depth );
}
function getDBType() {
return "varchar(255)";
}
function getLinkedObj() {
if ( !$this->linked_obj ) {
$this->linked_obj = new cobject( $this->lobj_name, $this->obj->recursion_depth );
}
return $this->linked_obj;
}
function lPost() {
if (is_array($_POST[$this->attr_name])) {
$this->obj->set($this->attr_name,implode(",",$_POST[$this->attr_name]));
} else {
$this->obj->set($this->attr_name,$_POST[$this->attr_name]);
}
}
function render_text( $crop = false ) {
$id = $this->getCurVal();
if ( $id ) $ids = explode( ",", $id );
$tpl = $this->obj->attrs[$this->attr_name]['templ'];
$outa = array();
if ( $ids ) {
foreach( $ids as $id ) {
$this->getLinkedObj()->byId( $id ); // Показывать удаленные
$outa[] = $this->getLinkedObj()->assign( $tpl );
}
if ($outa ) {
sort($outa);
}
}
return implode("; ", $outa);
}
function render_input() {
global $core;
$db = $this->getLinkedObj()->getDB();
$db2 = $db->q( $this->getLinkedObj()->getSelect( $this->sql_where ) );
$out = '';
$id = $this->getCurVal();
if ( $id ) $ids = explode( ",", $id );
$tpl = $this->obj->attrs[$this->attr_name]['templ'];
while ( $db2->r() ) {
$this->getLinkedObj()->lRow( $db2 );
$tt = $this->getLinkedObj()->assign( $tpl );
if ( $ids && in_array( $db2->f( 'id' ), $ids ) ) $checked = 'checked';
else $checked = '';
$out .= '
<div class="custom-controls-stacked">
<div class="custom-control custom-checkbox">
<input id="'.$this->attr_name.'_'.$db2->f( 'id' ).'" type="checkbox" name="'.$this->attr_name.'[]" class="checkbox custom-control-input" ' . $checked . ' value="'.$db2->f( 'id' ).'">
<label for="'.$this->attr_name.'_'.$db2->f( 'id' ).'" class="custom-control-label">' . $tt . '</label>
</div>
</div>
';
}
return $out;
}
function getFilter( $sql_where = '' ) {
$db = $this->getLinkedObj()->getDB();
$fname = $this->obj->obj_name . '_' . $this->attr_name;
$uniq_ids = array();
if ( $this->obj->obj_name ) {
$db3 = $this->obj->getDB()->q( $this->obj->getSelectEx( ' DISTINCT(`'.$this->attr_name.'`) as `'.$this->attr_name.'` ', '' ) );
while ( $db3->nr() ) {
$uniq_ids[] = $db3->f($this->attr_name);
}
} else {
$uniq_ids = array();
}
if (!$_GET[$fname]) {
$tmp = array('<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'\'" selected>Все</option>');
$tmp_s = array('<a href="'._getCurl(array( $fname, 'curpage' )).'"><b>Все</b></a>');
} else {
$tmp = array('<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'\'">Все</option>');
$tmp_s = array('<a href="'._getCurl(array( $fname, 'curpage' )).'">Все</a>');
}
$db2 = $db->q( $this->getLinkedObj()->getSelect( $sql_where) );
$c = 0;
while ( $db2->r() ) {
if ( $this->obj->obj_name && !in_array( $db2->f('id'), $uniq_ids ) ) continue;
$tpl = strip_tags( $this->getAttrTempl() );
$this->getLinkedObj()->lRow($db2);
$tpl = $this->getLinkedObj()->assign($tpl, true);
if ( strlen($tpl) > 100 ) $tpl = substr($tpl,0,100) . '...';
if ($_GET[$fname] != $db2->f('id')) {
$tplh = '<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'\'" value="'.$db2->f('id').'">' .$tpl . '</option>';
$tplh_s = '<a href="'._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'">' .$tpl . '</a>';
} else {
$tplh = '<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'\'" value="'.$db2->f('id').'" selected>' . $tpl . '</option>';
$tplh_s = '<a href="'._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'"><b>' .$tpl . '</b></a>';
$ret['sql'] = " AND FIND_IN_SET( ".$db2->f('id').",`" . $this->obj->obj_name . "`.`" . $this->attr_name . "`)" ;
}
$tmp[] = $tplh;
$tmp_s[] = $tplh_s;
$c++;
}
if ($c > 10 ) {
$ret['html'] = '<select class=\"form-control form-control-sm\" onChange="location.href=\''._getCurl(array( $fname, 'curpage' )).'&' . $fname .'=\'+$(this).val()">';
$ret['html'] .= implode('', $tmp);
$ret['html'] .= "</select>";
} else {
$ret['html'] .= implode(' | ', $tmp_s);
}
return $ret;
}
}
?>

View File

@ -0,0 +1,23 @@
<?php
class attr_checkbox extends attr {
function getDBType() {
return "int(1)";
}
function render_input() {
$html = '<input class="checkbox custom-control-input" id="chbx_' . $this->attr_name . '" type="checkbox" name="' . $this->attr_name . '" '.($this->getCurVal()?'checked':'').' value="1">';
return $html;
}
function render_text( $crop = false ) {
if ($this->getCurVal() ) $val = 'Да';
else $val = 'Нет';
return $val;
}
}
?>

View File

@ -0,0 +1,28 @@
<?php
class attr_color extends attr {
function getDBType() {
return "char(7)";
}
function render_input() {
$cv = $this->getCurVal();
$tpl = '<input type="color" name="'.$this->attr_name.'" id="'.$this->attr_name.'" value="'.$cv.'">';
return $tpl;
}
function render_text( $crop = false ) {
if ($crop) {
$color = $this->getCurVal();
if ($color) {
return '<span style="background:'.$color.'; color: '.$color.';" class="text-monospace">'.$color.'</span>';
} else {
return '';
}
}
return $this->getCurVal();
}
}
?>

View File

@ -0,0 +1,21 @@
<?php
class attr_color_picker extends attr {
public function getDBType() {
return "varchar(7)";
}
public function render_input() {
if ($this->obj->attrs[$this->attr_name]['mand']) {
$required = ' required = "required" ';
} else {
$required = '';
}
return '<input id="' . $this->attr_name . '" ' . $required . ' type="color" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '">';
}
}
?>

View File

@ -0,0 +1,213 @@
<?php
class attr_date extends attr {
function getDBType() {
return "int(12)";
}
function render_input() {
if ($this->getAttrSetting('mand'))
$defval = date('Y-m-d');
else
$defval = '';
$cv = $this->getCurVal();
$tpl = '<input type="date" class="form-control" autocomplete="off" name="'.$this->attr_name.'" id="'.$this->attr_name.'" value="'.($cv?date('Y-m-d', $cv):$defval).'">';
return $tpl;
}
function lPost() {
$time = strtotime($_POST[$this->attr_name] . ' 00:00:00');
if ( $time == false ) {
$time = $_POST[$this->attr_name];
}
if (empty($_POST[$this->attr_name]) && !$this->getAttrSetting('mand') ) {
$time = 0;
}
$this->obj->set($this->attr_name, $time);
}
function render_text( $crop = false ) {
if ( $this->getCurVal() ) {
return date('d.m.Y',$this->getCurVal());
} else {
return '';
}
}
function getFilter( $sql_where = '' ) {
$fname = $this->obj->obj_name . '_' . $this->attr_name;
if (!isset($_GET[$fname.'_year'])) $_GET[$fname.'_year'] = 0;
if (!isset($_GET[$fname.'_month'])) $_GET[$fname.'_month'] = 0;
if (!isset($_GET[$fname.'_week'])) $_GET[$fname.'_week'] = 0;
if (!isset($_GET[$fname.'_sday'])) $_GET[$fname.'_sday'] = 0;
$y = intval( $_GET[$fname.'_year'] );
$m = intval( $_GET[$fname.'_month'] );
$w = intval( $_GET[$fname.'_week'] );
$d = intval( $_GET[$fname.'_sday'] );
$ret = '';
// Display
// By date
// year
$nofirst = true ;
if ($y=='0')
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_year')) . "&".$fname.'_year'."=0' ><b>Все</b></a>";
else
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_year')) . "&".$fname.'_year'."=0' >Все</a>";
for ($year=2010;$year<=date('Y')+2;$year++) {
if ( $nofirst ) {
$html .= ' | ';
}
$nofirst = true;
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_year')) . "&".$fname.'_year'."=$year' >";
if ($y==$year)
$html.= "<b>$year</b>";
else
$html.= "$year";
$html.="</a>";
}
$html.= "<br>";
// month
if ($m=='0')
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_month')) . "&".$fname.'_month'."=0' ><b>Все</b></a>";
else
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_month')) . "&".$fname.'_month'."=0' >Все</a>";
for ($month=1;$month<=12;$month++) {
$html .= ' | ';
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_month')) . "&".$fname.'_month'."=$month' >";
if ($m==$month)
$html.= "<b>"._getMonthName($month)."</b>";
else
$html.= _getMonthName($month);
$html.="</a>";
}
$html.= "<br>";
// week
if ( $sql_where != 'noweek' ) {
if ($w=='0')
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_week')) . "&".$fname.'_week'."=0' ><b>Все</b></a>";
else
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_week')) . "&".$fname.'_week'."=0' >Все</a>";
$weeks = $this->getSeven(mktime(0,0,0, $m, 1, $y));
foreach ($weeks as $k=>$week) {
if ($k == 0) continue;
$html .= ' | ';
$html .="<a href='" . _getcurl(array( 'curpage', $fname.'_week')) . "&".$fname.'_week'."=".($k)."' >";
if ($w==$k)
$html .= "<b>".date('d', $weeks[($k-1)]).'-'.date('d', $week)."</b>";
else
$html .= date('d', $weeks[($k-1)]).'-'.date('d', $week);
$html.="</a>";
}
$html .= "<br>";
// day
if ( $sql_where != 'nodays' ) {
if ($d=='0')
$html.= "<a href='" . _getcurl(array( 'curpage', $fname.'_sday')) . "&".$fname.'_sday'."=0' ><b>Все</b></a>";
else
$html.= "<a href='" . _getcurl(array( 'curpage', $fname.'_sday')) . "&".$fname.'_sday'."=0' >Все</a>";
for ($i=1; $i<=date("t", mktime(0,0,0,$m,1,$y)); $i++) {
if ($i == 0) continue;
$html .= ' | ';
$html .= "<a href='" . _getcurl(array( 'curpage', $fname.'_sday')) . "&".$fname.'_sday'."=".($i)."' >";
if ($d==$i)
$html.= "<b>".$i."</b>";
else
$html.= $i;
$html.="</a>";
}
$html .= "<br>";
$html.= "<a href='" . _getcurl(
array($fname.'_year',
$fname.'_month',
$fname.'_week',
$fname.'_sday',
'curpage')
)."&".$fname.'_year'."=".date('Y')."&".$fname.'_month'."=".date('m')."&".$fname.'_week'."=0&".$fname.'_sday'."=".date('d')."'>";
if ( ( $d == date('d') ) && ($y == date('Y') ) && ($m == date('m') ) ) {
$html .="<b>Сегодня</b>";
} else {
$html .="Сегодня";
}
$html .="</a>";
}
}
// SQL
$range = $this->getTimeRangeMonth($y, $m);
if ( $w ) {
$ret .= ' AND
( '. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' >= ' . $weeks[($w-1)] . '
AND
'. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' <= ' . $weeks[$w] . ' )';
}elseif ( $d ) {
$ret .= ' AND
( '. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' >= ' . mktime(0,0,0,$m, $d, $y) . '
AND
'. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' <= ' . mktime(23,59,59,$m, $d, $y) . ' )';
} else {
$ret .= ' AND
( '. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' >= ' . $range['first'] . '
AND
'. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' <= ' . $range['last'] . ' )';
}
$r['sql'] = $ret;
$r['html'] = $html;
return $r; }
function getTimeRangeMonth($year, $month) {
if ($year && $month) {
$ret['first'] = mktime(0,0,0,$month,1,$year);
$ret['last'] = mktime(23,59,59,$month,date("t", $ret['first']),$year);
}
else {
if ($year) {
$ret['first'] = mktime(0,0,0,1,1,$year);
$ret['last'] = mktime(23,59,59,12,31,$year);
}
else {
$ret['first'] = 0;
$ret['last'] = 999999999999;
}
}
return $ret;
}
function getSeven ($date) { // С шагом в 7 дней
$day = date('d', $date);
$first_day = mktime(0,0,0,date('m', $date),1,date('Y', $date));
$last_day = mktime(23,59,59,date('m', $date),date('t', $date),date('Y', $date));
$ret[] = $first_day;
$tmp = $first_day;
while ( $tmp < $last_day ) {
$tmp = mktime(0,0,0,date('m', $tmp),date('d', $tmp)+7,date('Y', $tmp));
if ($tmp > $last_day)
$ret[] = $last_day;
else
$ret[] = $tmp;
}
return $ret;
}
}
?>

View File

@ -0,0 +1,44 @@
<?php
class attr_datereal extends attr {
function getDBType() {
return "date";
}
function render_input() {
if ($this->getAttrSetting('mand'))
$defval = date('Y-m-d');
else
$defval = '';
$cv = $this->getCurVal();
$tpl = '<input type="date" class="form-control" autocomplete="off" name="'.$this->attr_name.'" id="'.$this->attr_name.'" value="'.($cv?date('Y-m-d', $cv):$defval).'">';
return $tpl;
}
function lPost() {
$time = strtotime($_POST[$this->attr_name] . ' 00:00:00');
if ( $time == false ) {
$time = $_POST[$this->attr_name];
}
if (empty($_POST[$this->attr_name]) && !$this->getAttrSetting('mand') ) {
$time = 0;
}
$this->obj->set($this->attr_name, date('Y-m-d', $time));
}
function render_text( $crop = false ) {
if ( $this->getCurVal() ) {
return $this->getCurVal();
} else {
return '';
}
}
}
?>

View File

@ -0,0 +1,205 @@
<?php
class attr_datetime extends attr {
function getDBType() {
return "int(12)";
}
function render_input() {
if ($this->getAttrSetting('mand'))
$defval = date('Y-m-d\TH:i:00');
else
$defval = '';
$cv = $this->getCurVal();
$tpl = '<input type="datetime-local" class="form-control" name="'.$this->attr_name.'" id="'.$this->attr_name.'" value="'.($cv?date('Y-m-d\TH:i:s', $cv):$defval).'">';
return $tpl;
}
function lPost() {
$time = strtotime($_POST[$this->attr_name]);
if ( $time == false ) {
$time = $_POST[$this->attr_name];
}
$this->obj->set($this->attr_name, $time);
}
function render_text( $crop = false ) {
return date('d.m.Y H:i:s',$this->getCurVal());
}
function getFilter( $sql_where = '' ) {
$fname = $this->obj->obj_name . '_' . $this->attr_name;
if (!isset($_GET[$fname.'_year'])) $_GET[$fname.'_year'] = 0;
if (!isset($_GET[$fname.'_month'])) $_GET[$fname.'_month'] = 0;
if (!isset($_GET[$fname.'_week'])) $_GET[$fname.'_week'] = 0;
if (!isset($_GET[$fname.'_sday'])) $_GET[$fname.'_sday'] = 0;
$y = intval( $_GET[$fname.'_year'] );
$m = intval( $_GET[$fname.'_month'] );
$w = intval( $_GET[$fname.'_week'] );
$d = intval( $_GET[$fname.'_sday'] );
$ret = '';
// Display
// By date
// year
$nofirst = true ;
if ($y=='0')
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_year')) . "&".$fname.'_year'."=0' ><b>Все</b></a>";
else
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_year')) . "&".$fname.'_year'."=0' >Все</a>";
for ($year=2010;$year<=date('Y')+2;$year++) {
if ( $nofirst ) {
$html .= ' | ';
}
$nofirst = true;
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_year')) . "&".$fname.'_year'."=$year' >";
if ($y==$year)
$html.= "<b>$year</b>";
else
$html.= "$year";
$html.="</a>";
}
$html.= "<br>";
// month
if ($m=='0')
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_month')) . "&".$fname.'_month'."=0' ><b>Все</b></a>";
else
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_month')) . "&".$fname.'_month'."=0' >Все</a>";
for ($month=1;$month<=12;$month++) {
$html .= ' | ';
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_month')) . "&".$fname.'_month'."=$month' >";
if ($m==$month)
$html.= "<b>"._getMonthName($month)."</b>";
else
$html.= _getMonthName($month);
$html.="</a>";
}
$html.= "<br>";
// week
if ( $sql_where != 'noweek' ) {
if ($w=='0')
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_week')) . "&".$fname.'_week'."=0' ><b>Все</b></a>";
else
$html.="<a href='" . _getcurl(array( 'curpage', $fname.'_week')) . "&".$fname.'_week'."=0' >Все</a>";
$weeks = $this->getSeven(mktime(0,0,0, $m, 1, $y));
foreach ($weeks as $k=>$week) {
if ($k == 0) continue;
$html .= ' | ';
$html .="<a href='" . _getcurl(array( 'curpage', $fname.'_week')) . "&".$fname.'_week'."=".($k)."' >";
if ($w==$k)
$html .= "<b>".date('d', $weeks[($k-1)]).'-'.date('d', $week)."</b>";
else
$html .= date('d', $weeks[($k-1)]).'-'.date('d', $week);
$html.="</a>";
}
$html .= "<br>";
// day
if ( $sql_where != 'nodays' ) {
if ($d=='0')
$html.= "<a href='" . _getcurl(array( 'curpage', $fname.'_sday')) . "&".$fname.'_sday'."=0' ><b>Все</b></a>";
else
$html.= "<a href='" . _getcurl(array( 'curpage', $fname.'_sday')) . "&".$fname.'_sday'."=0' >Все</a>";
for ($i=1; $i<=date("t", mktime(0,0,0,$m,1,$y)); $i++) {
if ($i == 0) continue;
$html .= ' | ';
$html .= "<a href='" . _getcurl(array( 'curpage', $fname.'_sday')) . "&".$fname.'_sday'."=".($i)."' >";
if ($d==$i)
$html.= "<b>".$i."</b>";
else
$html.= $i;
$html.="</a>";
}
$html .= "<br>";
$html.= "<a href='" . _getcurl(
array($fname.'_year',
$fname.'_month',
$fname.'_week',
$fname.'_sday',
'curpage')
)."&".$fname.'_year'."=".date('Y')."&".$fname.'_month'."=".date('m')."&".$fname.'_week'."=0&".$fname.'_sday'."=".date('d')."'>";
if ( ( $d == date('d') ) && ($y == date('Y') ) && ($m == date('m') ) ) {
$html .="<b>Сегодня</b>";
} else {
$html .="Сегодня";
}
$html .="</a>";
}
}
// SQL
$range = $this->getTimeRangeMonth($y, $m);
if ( $w ) {
$ret .= ' AND
( '. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' >= ' . $weeks[($w-1)] . '
AND
'. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' <= ' . $weeks[$w] . ' )';
}elseif ( $d ) {
$ret .= ' AND
( '. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' >= ' . mktime(0,0,0,$m, $d, $y) . '
AND
'. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' <= ' . mktime(23,59,59,$m, $d, $y) . ' )';
} else {
$ret .= ' AND
( '. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' >= ' . $range['first'] . '
AND
'. ($this->obj->obj_name?($this->obj->obj_name. '.'):'') . $this->attr_name .' <= ' . $range['last'] . ' )';
}
$r['sql'] = $ret;
$r['html'] = $html;
return $r;
}
function getTimeRangeMonth($year, $month) {
if ($year && $month) {
$ret['first'] = mktime(0,0,0,$month,1,$year);
$ret['last'] = mktime(23,59,59,$month,date("t", $ret['first']),$year);
}
else {
if ($year) {
$ret['first'] = mktime(0,0,0,1,1,$year);
$ret['last'] = mktime(23,59,59,12,31,$year);
}
else {
$ret['first'] = 0;
$ret['last'] = 999999999999;
}
}
return $ret;
}
function getSeven ($date) { // С шагом в 7 дней
$day = date('d', $date);
$first_day = mktime(0,0,0,date('m', $date),1,date('Y', $date));
$last_day = mktime(23,59,59,date('m', $date),date('t', $date),date('Y', $date));
$ret[] = $first_day;
$tmp = $first_day;
while ( $tmp < $last_day ) {
$tmp = mktime(0,0,0,date('m', $tmp),date('d', $tmp)+7,date('Y', $tmp));
if ($tmp > $last_day)
$ret[] = $last_day;
else
$ret[] = $tmp;
}
return $ret;
}
}
?>

View File

@ -0,0 +1,25 @@
<?php
class attr_datetime_modify extends attr {
function getDBType() {
return "int(12)";
}
function render_input() {
return '';
}
function lPost() {
$this->obj->set($this->attr_name, time());
}
function presave() {
// $this->obj->set($this->attr_name, time());
}
function render_text( $crop = false ) {
return date('d.m.Y H:i:s',$this->getCurVal());
}
}
?>

View File

@ -0,0 +1,44 @@
<?php
class attr_datetimereal extends attr {
function getDBType() {
return "datetime";
}
function render_input() {
if ($this->getAttrSetting('mand'))
$defval = date('Y-m-d\TH:i:00');
else
$defval = '';
$cv = $this->getCurVal();
$tpl = '<input type="datetime-local" class="form-control" name="'.$this->attr_name.'" id="'.$this->attr_name.'" value="'.($cv?date('Y-m-d\TH:i:s', $cv):$defval).'">';
return $tpl;
}
function lPost() {
$time = strtotime($_POST[$this->attr_name]);
if ( $time == false ) {
$time = $_POST[$this->attr_name];
}
if (empty($_POST[$this->attr_name]) && !$this->getAttrSetting('mand') ) {
$time = 0;
}
$this->obj->set($this->attr_name, date('Y-m-d H:i:s', $time));
}
function render_text( $crop = false ) {
if ( $this->getCurVal() ) {
return $this->getCurVal();
} else {
return '';
}
}
}
?>

View File

@ -0,0 +1,51 @@
<?php
class attr_email extends attr {
function getDBType() {
return "varchar(255)";
}
function lPost() {
$val = trim(strtolower($_POST[$this->attr_name]));
$this->obj->set($this->attr_name, $val);
}
function render_text( $crop = false ) {
return $this->getCurVal();
}
function validate() {
if ( !preg_match("/^([a-z0-9_\.-]+)@([a-z0-9_\.-]+)\.([a-z\.]{2,6})$/i",strtolower($this->getCurVal()) ) ) {
return 'Неверный формат ввода';
}
}
function render_input() {
return '<input id="' . $this->attr_name . '" type="text" class="form-control" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '">';
}
function getFilter( $sql_where = '' ) {
$fname = $this->obj->obj_name . '_' . $this->attr_name;
$html = '<input class="form-control form-control-sm" id="_f_'.$fname.'" name="'.$fname.'" value="'.htmlentities($_GET[$fname]).'" onkeypress="int13_filter_'.$fname.'();" onKeyUp>
<script>
function int13_filter_'.$fname.'() {
if (window.event.keyCode == 13 || window.event.keyCode == 9) { location.href="'._getCurl(array( $fname, 'curpage' )).'&'.$fname.'=" + $("#_f_'.$fname.'").val(); return true; }
}
</script>';
$sql = '';
if ( $_GET[$fname] ) {
$sql = ' AND `' . $this->attr_name . '` LIKE "%' . db_escape_string($_GET[$fname]) . '%" ';
}
return array('html'=> $html, 'sql'=> $sql);
}
}
?>

View File

@ -0,0 +1,61 @@
<?php
class attr_file extends attr {
function getDBType() {
return "int(12)";
}
function render_input() {
$html = '<input class="input" type="file" name="' . $this->attr_name . '">';
$html .= '<input class="input" type="hidden" name="' . $this->attr_name . '" value="1">';
if ( $this->getCurVal() ) {
$html .= '<br><label><input class="checkbox" type="checkbox" name="' . $this->attr_name . '_del" value="1"> Удалить</label>';
}
return $html;
}
function lPost() {
$tmpObj = new cobject( '_sys_files' );
$file = $_FILES[$this->attr_name];
$fileContent = file_get_contents($file['tmp_name']);
$fname = md5($fileContent);
$fpath = substr($fname,0,2);
$fpath2 = substr($fname,2,2);
@mkdir( _FILES_DIR_ . $fpath . '/' . $fpath2, 0777, true );
$fname = $fpath .'/' . $fpath2 . '/' . $fname;
if ($_POST[$this->attr_name . '_del']) {
$this->obj->set( $this->attr_name, 0 );
}
if (!$file['error']) {
if ( move_uploaded_file( $file['tmp_name'], _FILES_DIR_.$fname ) ) {
$tmpObj->set('filename', $fname );
$tmpObj->set('realname', $file['name'] );
$tmpObj->set('ext', $file['type'] );
$tmpObj->save();
$this->obj->set( $this->attr_name, $tmpObj->id );
} else {
die('Error: проверьте права на сохранение в ' . _FILES_DIR_ . $fpath . '/' . $fpath2);
}
}
}
function render_text( $crop = false ) {
if ($crop) {
$val = '<a href="file.php?id='.$this->getCurVal().'">Скачать</a>';
} else {
$val = $this->getCurVal();
}
return $val;
}
}
?>

View File

@ -0,0 +1,56 @@
<?php
class attr_file_direct extends attr {
function getDBType() {
return "varchar(255)";
}
function render_input() {
$html = '<input class="input" type="file" name="' . $this->attr_name . '">';
$html .= '<input class="input" type="hidden" name="' . $this->attr_name . '" value="1">';
if ( $this->getCurVal() ) {
$html .= '<br><label><input class="checkbox" type="checkbox" name="' . $this->attr_name . '_del" value="1"> Удалить</label>';
}
return $html;
}
function lPost() {
$file = $_FILES[$this->attr_name];
$fname = md5(microtime(true));
if ($_POST[$this->attr_name . '_del']) {
$this->obj->set( $this->attr_name, '' );
}
if (!$file['error']) {
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
$fpath = substr($fname,0,2);
@mkdir( _FILES_DIR_ . $fpath );
$fpath2 = substr($fname,2,2);
@mkdir( _FILES_DIR_ . $fpath . '/' . $fpath2);
$fname = $fpath .'/' . $fpath2 . '/'. $file['name'];
if ( move_uploaded_file( $file['tmp_name'], _FILES_DIR_.$fname ) ) {
$this->obj->set( $this->attr_name, $fname );
}
}
}
function render_text( $crop = false ) {
if ($crop) {
$val = '<a href="'._STATIC_ROOT_.'files/'.$this->getCurVal().'">Скачать</a>';
} else {
$val = $this->getCurVal();
}
return $val;
}
}
?>

View File

@ -0,0 +1,62 @@
<?php
class attr_file_private extends attr {
function getDBType() {
return "int(12)";
}
function render_input() {
$html = '<input class="input" type="file" name="' . $this->attr_name . '">';
$html .= '<input class="input" type="hidden" name="' . $this->attr_name . '" value="1">';
if ( $this->getCurVal() ) {
$html .= '<br><label><input class="checkbox" type="checkbox" name="' . $this->attr_name . '_del" value="1"> Удалить</label>';
}
return $html;
}
function lPost() {
$tmpObj = new cobject( '_sys_files' );
$file = $_FILES[$this->attr_name];
$fileContent = file_get_contents($file['tmp_name']);
$fname = md5($fileContent);
$fpath = substr($fname,0,2);
$fpath2 = substr($fname,2,2);
@mkdir( _FILES_DIR_ . $fpath . '/' . $fpath2, 0777, true );
$fname = $fpath .'/' . $fpath2 . '/' . $fname;
if ($_POST[$this->attr_name . '_del']) {
$this->obj->set( $this->attr_name, 0 );
}
if (!$file['error']) {
if ( move_uploaded_file( $file['tmp_name'], _FILES_DIR_.$fname ) ) {
$tmpObj->set('filename', $fname );
$tmpObj->set('realname', $file['name'] );
$tmpObj->set('ext', $file['type'] );
$tmpObj->set('private', 1 );
$tmpObj->save();
$this->obj->set( $this->attr_name, $tmpObj->id );
} else {
die('Error: проверьте права на сохранение в ' . _FILES_DIR_ . $fpath . '/' . $fpath2);
}
}
}
function render_text( $crop = false ) {
if ($crop) {
$val = '<a href="file.php?id='.$this->getCurVal().'">Скачать</a>';
} else {
$val = $this->getCurVal();
}
return $val;
}
}
?>

View File

@ -0,0 +1,35 @@
<?php
class attr_float extends attr {
function getDBType() {
return "decimal(14,4)";
}
function render_input() {
$val = $this->getCurVal() + 0; // auto format trick
$val = number_format ($val, 3, '.','');
if ( $this->getAttrSetting('mand')) {
return '<input id="' . $this->attr_name . '" type="text" name="' . $this->attr_name . '" value="' .$val . '" class="form-control" required="required">';
} else {
return '<input id="' . $this->attr_name . '" type="text" name="' . $this->attr_name . '" value="' .$val . '" class="form-control">';
}
}
function render_text( $crop = false ) {
if ( !$this->getCurVal() ) return '0';
$dec = 2;
$val = $this->getCurVal() + 0; // auto format trick
if ( $this->obj->attrs[$this->attr_name]['templ'] ) {
$val = $this->getCurVal() + 0; // auto format trick
return floatval($val);
}
return number_format ($val, $dec, '.','');
}
}
?>

View File

@ -0,0 +1,54 @@
<?php
class attr_full_url extends attr {
function render_text( $crop = false ) {
return $this->getCurVal();
}
function lPost() {
$url = preg_replace('/[^A-Za-z0-9_\-\/\.]/','', $_POST[$this->attr_name]);
if (!$this->getCurVal()) {
$url = strtolower($url);
}
$this->obj->set($this->attr_name,$url);
}
function render_input() {
$templ = $this->getAttrTempl();
list($prefix, $cat_id ) = explode('|', $templ);
if ( $this->getCurVal() && $this->obj->id ) {
return '<div class="form-control"><input id="' . $this->attr_name . '" type="hidden" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '">
<a target="_blank" class="py-2" href="'._SHOP_ROOT_.$this->getCurVal().'"><i class="far fa-external-link"></i></a> '.$this->getCurVal().'</div>
';
} else {
$str = '<input id="' . $this->attr_name . '" type="text" class="form-control" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '" required="required">'."
<script>
$(document).ready( function() {
$('#title').keyup( function() {
if ( $('#url').attr('type') == 'hidden' ) return true;";
if ($prefix) {
$str .= "$('#url').val( '".$prefix."/' + translateStr( $('#title').val() ) + '-' + Math.floor((Math.random()*10000)+1) + '.htm');";
} else {
$str .= "$('#url').val( translateStr( $('#title').val() ) + '-' + Math.floor((Math.random()*10000)+1) + '.htm' );";
}
$str.="
return true;
});
});
</script>";
return $str;
}
}
}
?>

View File

@ -0,0 +1,27 @@
<?php
class attr_geometry extends attr {
public function getDBType() {
return "GEOMETRY";
}
public function render_input() {
return "no editable";
}
public function render_text($crop) {
return 'serialized data';
}
public function lPost() {
}
public function presave() {
}
}
?>

View File

@ -0,0 +1,63 @@
<?php
class attr_icon extends attr {
function getDBType() {
return "TEXT";
}
function render_input() {
$html = '';
if ( $this->getCurVal() ) {
$html .= '<img class="mx-2" src="'.$this->getCurVal().'" style="height: 24px; vertical-align: middle;">';
}
$html .= '<label class="btn btn-gray"><input class="d-none" type="file" id="img_' . $this->attr_name . '" name="' . $this->attr_name . '"> Выбрать файл</label>';
$html .= '<input class="input" type="hidden" name="' . $this->attr_name . '" value="'.$this->getCurVal().'">';
if ( $this->getCurVal() ) {
$html .= '
<div class="custom-control custom-checkbox">
<input class="checkbox custom-control-input" type="checkbox" id="' . $this->attr_name . '_del" name="' . $this->attr_name . '_del" value="1">
<label for="' . $this->attr_name . '_del" class="custom-control-label"> Удалить</label>
</div>';
}
return $html;
}
function lPost() {
if ( substr( $this->attr_name, -8 ) == '_preview' ) {
return;
}
$tmpObj = new cobject( '_sys_files' );
$file = $_FILES[$this->attr_name];
$nn = md5(microtime(true));
if ($_POST[$this->attr_name . '_del']) {
$this->obj->set( $this->attr_name, '' );
}elseif ($_POST[$this->attr_name]) {
$this->obj->set( $this->attr_name, $_POST[$this->attr_name] );
}
if (!$file['error']) {
$this->obj->set($this->attr_name, 'data:'.$file['type'].';base64,' . base64_encode(file_get_contents($file['tmp_name'])) );
}
}
function render_text( $crop = false ) {
if ($crop) {
if ( $this->getCurVal() ) {
$val = $this->getCurVal();
} else {
$val = '';
}
} else {
$val = $this->getCurVal();
}
return $val;
}
}
?>

View File

@ -0,0 +1,125 @@
<?php
class attr_image extends attr {
function getDBType() {
return "int(12)";
}
function render_input() {
$html = '';
if ( $this->getCurVal() ) {
$html .= '<a href="img.php?id='.$this->getCurVal().'" data-fancybox><img class="mx-1" src="img.php?id='.$this->getCurVal().'" style="height: 30px; vertical-align: middle;"></a>';
}
$html .= '<label class="btn btn-gray"><input class="d-none" type="file" id="img_' . $this->attr_name . '" name="' . $this->attr_name . '"> Выбрать файл</label>';
$html .= '<input class="input" type="hidden" name="' . $this->attr_name . '" value="'.$this->getCurVal().'">';
if ( $this->getCurVal() ) {
$html .= '
<div class="custom-control custom-checkbox">
<input class="checkbox custom-control-input" type="checkbox" id="' . $this->attr_name . '_del" name="' . $this->attr_name . '_del" value="1">
<label for="' . $this->attr_name . '_del" class="custom-control-label"> Удалить</label>
</div>';
}
return $html;
}
function lPost() {
if ( substr( $this->attr_name, -8 ) == '_preview' ) {
return;
}
if ($_POST[$this->attr_name . '_del']) {
$this->obj->set( $this->attr_name, 0 );
}
if ($_POST[$this->attr_name]) {
$this->obj->set( $this->attr_name, $_POST[$this->attr_name] );
}
$file = $_FILES[$this->attr_name];
if (isset($file['error']) && !$file['error']) {
require_once (_CORE_DIR . 'image.transform.core.php');
$tmpObj = new cobject( '_sys_files' );
$file = $_FILES[$this->attr_name];
$fileContent = file_get_contents($file['tmp_name']);
// Имя файла основано на содержимом
$fname = md5($fileContent);
$fpath = substr($fname,0,2);
$fpath2 = substr($fname,2,2);
@mkdir( _FILES_DIR_ . $fpath . '/' . $fpath2, 0777, true );
$fname = $fpath .'/' . $fpath2 . '/' . $fname;
$toSize = $this->obj->attrs[$this->attr_name]['templ'];
if (!file_exists(_FILES_DIR_ . $fname .'_'. $toSize) ) {
$im = imagecreatefromstring($fileContent);
// Сохраняем картинку
$res = imagejpeg($im, _FILES_DIR_ . $fname.'_' , 95 );
//Ресайзим если нужно
if ($toSize != "") {
$p = explode('x', $toSize);
if (count($p) == 2) {
$tr = new imageTransform(_FILES_DIR_ . $fname .'_', 'image/jpeg');
$tr->resize($p[0], $p[1], true);
$tr->save(_FILES_DIR_ .$fname .'_'. $toSize);
}
}
}
// Сохраняем в базу
$fobj = new cobject('_sys_files');
$fobj->set('filename', $fname . '_'. $toSize);
$fobj->set('ext','image/jpeg');
$fobj->set('realname', $file['name']);
$fobj->save();
// Сохраняем в объект
$this->obj->set( $this->attr_name, $fobj->id );
// Автопревью
if ( isset($this->obj->attrs[$this->attr_name.'_preview']) && $this->obj->attrs[$this->attr_name.'_preview']['templ'] ) {
$pre_size = $this->obj->attrs[$this->attr_name.'_preview']['templ'];
if ($pre_size != "" ) {
// Сохраняем в базу
$fobj = new cobject('_sys_files');
$fobj->set('filename', $fname . '_' . $pre_size );
$fobj->set('ext','image/jpeg');
$fobj->set('realname', 'preview_'.$file['name']);
$fobj->save();
$this->obj->set( $this->attr_name.'_preview', $fobj->id );
copy(_FILES_DIR_.$fname . '_'. $toSize, _FILES_DIR_.$fname.'_' . $pre_size );
$p = explode('x',$pre_size);
$tr = new imageTransform(_FILES_DIR_ . $fname.'_' . $pre_size, 'image/jpeg');
$tr->resize($p[0], $p[1], true);
$tr->save(_FILES_DIR_ .$fname.'_' . $pre_size );
}
}
}
}
function render_text( $crop = false ) {
if ($crop) {
$val = '<a href="img.php?id='.$this->getCurVal().'"><img src="img.php?id='.$this->getCurVal().'" height="48"></a>';
} else {
$val = $this->getCurVal();
$val = getImagePath($val);
}
return $val;
}
}
?>

View File

@ -0,0 +1,31 @@
<?php
class attr_input extends attr {
function render_text( $crop = false ) {
return $this->getCurVal();
}
function getFilter( $sql_where = '' ) {
$fname = $this->obj->obj_name . '_' . $this->attr_name;
$html = '<input class="form-control form-control-sm" id="_f_'.$fname.'" name="'.$fname.'" value="'.htmlentities($_GET[$fname]).'" onkeypress="int13_filter_'.$fname.'();" onKeyUp>
<script>
function int13_filter_'.$fname.'() {
if (window.event.keyCode == 13 || window.event.keyCode == 9) { location.href="'._getCurl(array( $fname, 'curpage' )).'&'.$fname.'=" + $("#_f_'.$fname.'").val(); return true; }
}
</script>';
$sql = '';
if ( $_GET[$fname] ) {
$sql = ' AND `' . $this->attr_name . '` LIKE "%' . db_escape_string($_GET[$fname]) . '%" ';
}
return array('html'=> $html, 'sql'=> $sql);
}
}
?>

View File

@ -0,0 +1,16 @@
<?php
class attr_int12 extends attr {
function getDBType() {
return "int(12)";
}
function render_input() {
return '<input id="' . $this->attr_name . '" type="number" class="form-control" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '">';
}
}
?>

View File

@ -0,0 +1,27 @@
<?php
class attr_json extends attr {
function getDBType() {
return "text";
}
function render_input() {
return '<input type="hidden" id="' . $this->attr_name.'" name="' . $this->attr_name.'" value=\'' .$this->getCurVal() . '\'/>';
}
function render_text( $crop = false ) {
$val = 'JSON DATA';
return $val;
}
function lPost() {
}
function presave() {
}
}
?>

View File

@ -0,0 +1,95 @@
<?php
class attr_mobile_phone extends attr {
function getDBType() {
return "bigint(10)";
}
function lPost() {
if ( defined('_ADMINKA_') ) {
$val = preg_replace('/[^0-9]/','', $_POST[$this->attr_name]);
$this->obj->set($this->attr_name, $val);
} else {
$val = preg_replace('/[^0-9]/','', $_POST[$this->attr_name]);
if ($val) {
$this->obj->set($this->attr_name, _PHONE_PREFIX . substr($val,-_PHONE_LEN));
} else {
$this->obj->set($this->attr_name, '');
}
}
}
function render_text( $crop = false ) {
$p = $this->getCurVal();
// Форматиирование телефонов
switch( strlen($p) ) {
case 11: // RU + KZ
return '+' . substr($p,0,1) . '('.substr($p,1,3).')'.substr($p,-(strlen($p) - 4 ));
break;
case 12: // BY
return '+' . substr($p,0,3) . '('.substr($p,3,2).')'.substr($p,-(strlen($p) - 5 ));
break;
case 3:
return $p;
break;
case 1:
if (!$p) {
return '';
} else {
return $p;
}
default:
return '('.substr($p,0,3).')'.substr($p,-(strlen($p) - 3 ));
break;
}
}
function validate() {
if ( defined('_ADMINKA_') ) {
if ( !preg_match('/\d{10,}/', $this->getCurVal() ) ) {
return 'Введите телефон в формате<br> +[код страны][код города][телефон]';
}
return;
} else {
$fulllen = _PHONE_LEN + strlen(_PHONE_PREFIX);
if ( !preg_match('/\d{'.$fulllen.'}/', $this->getCurVal() ) ) {
return 'Введите телефон в формате<br> +' . _PHONE_PREFIX . str_repeat('X', _PHONE_LEN);
}
}
}
function render_input() {
if (defined('_PHONE_PLACEHOLDER')) {
$placeholder = _PHONE_PLACEHOLDER;
} else {
$placeholder = '+[код страны][код города][телефон]';
}
return '<input id="' . $this->attr_name . '" type="text" placeholder="'.$placeholder.'" class="form-control" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '" '.($this->obj->attrs[$this->attr_name]['mand']?'required':'').'>';
}
function getFilter( $sql_where = '' ) {
$fname = $this->obj->obj_name . '_' . $this->attr_name;
$html = '<input class="form-control form-control-sm" id="_f_'.$fname.'" name="'.$fname.'" value="'.htmlentities($_GET[$fname]).'" onkeypress="int13_filter_'.$fname.'();" onKeyUp>
<script>
function int13_filter_'.$fname.'() {
if (window.event.keyCode == 13 || window.event.keyCode == 9) { location.href="'._getCurl(array( $fname, 'curpage' )).'&'.$fname.'=" + $("#_f_'.$fname.'").val(); return true; }
}
</script>';
$sql = '';
if ( $_GET[$fname] ) {
$sql = ' AND `' . $this->attr_name . '` LIKE "%' . db_escape_string($_GET[$fname]) . '%" ';
}
return array('html'=> $html, 'sql'=> $sql);
}
}
?>

View File

@ -0,0 +1,47 @@
<?php
class attr_modulelist extends attr {
function getDBType() {
return "text";
}
function render_input() {
$templ = $this->getAttrTempl();
$val = $this->getCurVal();
list($dir, $exts) = explode(";", $templ );
$ext = explode(',', $exts );
$file_list = scandir( _ENGINE_DIR . $dir );
$html = '<select class="form-control" name="' . $this->attr_name.'" class="select" id="' . $this->attr_name.'">';
if (!$this->getAttrSetting('mand') ) {
$html .= '<option value="">[---]</option>';
}
sort($file_list);
foreach( $file_list as $v ) {
$e = substr($v,-4);
if (in_array($e, $ext ) ){
if ( $v == $val ) {
$html .= '<option value="'.$v.'" selected>'.$v.'</option>';
} else {
$html .= '<option value="'.$v.'">'.$v.'</option>';
}
}
}
$html .= '</select>';
return $html;
}
function render_text( $crop = false ) {
$val = $this->getCurVal();
if ( $crop ) {
$val = substr(strip_tags($val),0, 100);
}
return $val;
}
}
?>

View File

@ -0,0 +1,28 @@
<?php
class attr_money extends attr {
function getDBType() {
return "decimal(14,4)";
}
function render_input() {
if ( $this->getAttrSetting('mand')) {
return '<input autocomplete="off" id="' . $this->attr_name . '" type="number" step="0.01" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '" class="form-control" required="required">';
} else {
return '<input autocomplete="off" id="' . $this->attr_name . '" type="number" step="0.01" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '" class="form-control">';
}
}
function render_text( $crop = false ) {
if ( !$this->getCurVal() ) return '0';
if ( $this->obj->attrs[$this->attr_name]['templ'] ) $c = true; else $c= false;
return nf($this->getCurVal(), $c);
}
}
?>

View File

@ -0,0 +1,22 @@
<?php
class attr_passwd extends attr {
function lPost() {
if ( $_POST[$this->attr_name] != "***" ) {
$this->obj->set($this->attr_name,md5($_POST[$this->attr_name]));
}
}
function render_input() {
return '<input type="password" class="form-control" name="' . $this->attr_name.'" value="***">';
}
function render_text( $crop = false ) {
return '***';
}
}
?>

View File

@ -0,0 +1,38 @@
<?php
class attr_redactor_html extends attr {
function getDBType() {
return "text";
}
function render_input() {
return '<textarea class="textarea" id="' . $this->attr_name.'" name="' . $this->attr_name.'">' .html_entity_decode($this->getCurVal()) . '</textarea>
<script>$("#' . $this->attr_name.'").redactor( { imageUpload: "img_uploader.php", fileUpload: "file_uploader.php" } );</script>
';
}
function render_text( $crop = false ) {
$val = $this->getCurVal();
if ( $crop ) {
$val = mb_substr(strip_tags(html_entity_decode($val)),0, 100,'UTF-8');
}
return html_entity_decode($val);
}
function lPost() {
if ( ini_get('magic_quotes_gpc') ) {
$this->obj->set($this->attr_name,stripslashes($_POST[$this->attr_name]));
} else {
$this->obj->set($this->attr_name,$_POST[$this->attr_name]);
}
}
function presave() {
$data = htmlspecialchars( html_entity_decode( $this->getCurVal(), NULL, 'UTF-8' ), NULL, 'UTF-8' );
$this->obj->set($this->attr_name, $data );
}
}
?>

View File

@ -0,0 +1,38 @@
<?php
class attr_redactor_html_private extends attr {
function getDBType() {
return "text";
}
function render_input() {
return '<textarea class="textarea" id="' . $this->attr_name.'" name="' . $this->attr_name.'">' .html_entity_decode($this->getCurVal()) . '</textarea>
<script>$("#' . $this->attr_name.'").redactor( { imageUpload: "img_uploader.php?private=1", fileUpload: "file_uploader.php" } );</script>
';
}
function render_text( $crop = false ) {
$val = $this->getCurVal();
if ( $crop ) {
$val = mb_substr(strip_tags(html_entity_decode($val)),0, 100,'UTF-8');
}
return html_entity_decode($val);
}
function lPost() {
if ( ini_get('magic_quotes_gpc') ) {
$this->obj->set($this->attr_name,stripslashes($_POST[$this->attr_name]));
} else {
$this->obj->set($this->attr_name,$_POST[$this->attr_name]);
}
}
function presave() {
$data = htmlspecialchars( html_entity_decode( $this->getCurVal(), NULL, 'UTF-8' ), NULL, 'UTF-8' );
$this->obj->set($this->attr_name, $data );
}
}
?>

View File

@ -0,0 +1,204 @@
<?php
class attr_tags extends attr {
var $linked_obj;
var $sql_where;
var $lobj_name;
var $hashCode = 'tags';
var $presaveData = [];
var $beenLPost = false;
function __construct( $attr_name, $obj ) {
$this->attr_name = $attr_name;
$this->obj = $obj;
$full_type = $obj->attrs[$attr_name]['type'];
$this->lobj_name = 'global_tags';
$this->lattr_name = 'entity_id';
$this->linked_obj = new cobject($this->lobj_name);
$this->hashCode = md5($this->lobj_name . $this->attr_name . $this->obj->id);
}
function getDBType() {
return "int(1)";
}
function lPost() {
$this->beenLPost = true;
$data = $_POST[$this->hashCode];
$curattrs = [];
// Заполняем данные из POST
if (is_array($data) && !empty($data) ) {
$sql = "SELECT id, title, tag_group_id FROM `global_tags_titles`
WHERE id in (".implode(",", $data).")
";
$db2 = $this->linked_obj->getDB()->q($sql);
while( $db2->nr() ) {
$curattrs[$db2->f('tag_group_id')][] = array('id' => $db2->f('id'), 'title' => $db2->f('title'));
}
}
$this->presaveData = $curattrs;
$this->obj->diffed[] = $this->attr_name;
}
function render_text( $crop = false ) {
$data = $this->getCurVal();
$html = '';
foreach($data as $group_id => $vals) {
foreach( $vals as $val ) {
$html .='<span class="badge badge-info mx-1">'.$val['title'].'</span>';
}
}
return $html;
}
function getCurVal() {
// Если была подгрузка из POST, то берём оттуда
if ($this->beenLPost) {
return $this->presaveData;
}
// Иначе из базы
$curattrs = [];
$sql = "SELECT global_tags_titles.id, global_tags_titles.title, `".$this->lobj_name."`.tag_group_id FROM `".$this->lobj_name."`
LEFT JOIN `global_tags_titles` ON (`global_tags_titles`.`id` = `".$this->lobj_name."`.`tag_id`)
WHERE `".$this->lattr_name."` = '".$this->obj->id."' ";
$db2 = $this->linked_obj->getDB()->q( $sql );
while( $db2->nr() ) {
$curattrs[$db2->f('tag_group_id')][] = array('id' => $db2->f('id'), 'title' => $db2->f('title'));
}
return $curattrs;
}
function render_input() {
$obj_id = $this->linked_obj->id;
$groupObj = new cobject('global_tags_groups');
$titleObj = new cobject('global_tags_titles');
$out = '<table id="table'.$this->hashCode.'" class="table table-sm bg-white" style="table-layout: fixed; width: 100%;">
<thead>
<tr><th style=" width: 200px;">Характеристика</th><th>Значение</th></tr>
</thead>
<tbody>
';
$groupList = $groupObj->getList(' ORDER BY `title` ');
// Получаем текущие значения из базы или POST
$curattrs = $this->getCurVal();
$addList = [];
foreach ($groupList as $group_id => $group_title) {
if (isset($curattrs[$group_id])) {
$out .= '<tr><td class="align-middle">' . $group_title . "</td><td>
<select name='".$this->hashCode."[]' id='filter_".$this->hashCode."_".$group_id."' data-addLink='tags_loader.php?add=1&group_id=".$group_id."&str=' multiple style='width: 100%;'> ";
foreach( $curattrs[$group_id] as $vals ) {
$out .= '<option selected value="'.$vals['id'].'">'.$vals['title'].'</option>';
}
$out .= "</select></td></tr>
<script>
$(document).ready( function() {
addSelector_".$this->hashCode."('filter_".$this->hashCode."_".$group_id."', '".$group_id."');
});
</script>";
} else {
$addList[] = '<option value="'.$group_id.'">'.$group_title.'</option>';
}
}
$out .= '</tbody>
<tfoot>
<tr><td>
<select id="addfilter_'.$this->hashCode.'" style="width:100%">';
$out .= implode(" ", $addList);
$out .= '</select>
</td><td>
<a href="javascript:addLine_'.$this->hashCode.'(\'addfilter_'.$this->hashCode.'\');" class="btn btn-primary">Добавить</a>
</td></tr>
</tfoot>
</table>
<input type="hidden" name="'.$this->attr_name.'" value="1">
';
$out .= "<script>
$(document).ready( function() {
$('#addfilter_".$this->hashCode."').chosen();
});
function addSelector_".$this->hashCode."(selector, id ) {
$.getJSON('tags_loader.php?preload=1&group_id=' + id, function(data) {
var currentOptions = $('#' + selector + ' option').map(function() { return parseInt(this.value) }).get();
for(i in data ) {
if ($.inArray(parseInt(data[i].value), currentOptions) === -1 ) {
console.log('addme');
$('#' + selector).append('<option value=\"' + data[i].value + '\">'+data[i].text+'</option>');
}
}
$('#' + selector).trigger('liszt:updated');
} );
$('#' + selector).ajaxChosen({
type: 'GET', url: 'tags_loader.php?group_id=' + id,
dataType: 'json',
minTermLength: 1
},
function (data) {
var results = [];
$.each(data, function (i, val) {
results.push({ value: val.value, text: val.text });
});
return results;
}
);
}
function addLine_".$this->hashCode."(selector) {
var attr_id = $('#' + selector).val();
var text = $('#' +selector + ' option:selected').text();
$('#table".$this->hashCode." tbody').append('<tr><td class=\'align-middle\'>'+text+'</td><td><select name=\"".$this->hashCode."[]\" id=\"filter_".$this->hashCode."_'+attr_id+'\" data-addLink=\"tags_loader.php?add=1&group_id='+attr_id+'&str=\" multiple style=\"min-width: 100%;\"></select></td></tr>');
addSelector_".$this->hashCode."('filter_".$this->hashCode."_' + attr_id, attr_id );
$('#' +selector + ' option:selected').remove();
$('#' + selector).trigger('liszt:updated');
}
</script> ";
return $out;
}
// Сохраняем после сохранения основного объекта
function postsave() {
if (!$this->obj->id ) return false;
// Очищаем старые значения
$this->linked_obj->getDB()->q('DELETE FROM `'.$this->lobj_name.'` WHERE `'.$this->lattr_name.'` = "'.$this->obj->id.'"');
foreach($this->presaveData as $group_id => $vals) {
foreach( $vals as $val ) {
$this->linked_obj->byId(0);
$this->linked_obj->set($this->lattr_name, $this->obj->id);
$this->linked_obj->set('tag_id', $val['id']);
$this->linked_obj->set('tag_group_id', $group_id);
$this->linked_obj->save();
}
}
}
}
?>

View File

@ -0,0 +1,23 @@
<?php
class attr_textarea extends attr {
function getDBType() {
return "text";
}
function render_input() {
return '<textarea class="textarea form-control" id="' . $this->attr_name.'" name="' . $this->attr_name.'">' .$this->getCurVal() . '</textarea>';
}
function render_text( $crop = false ) {
$val = $this->getCurVal();
if ( $crop ) {
$val = substr(strip_tags($val),0, 100);
}
return $val;
}
}
?>

View File

@ -0,0 +1,23 @@
<?php
class attr_textarea_html extends attr {
function getDBType() {
return "text";
}
function render_input() {
return '<textarea class="textarea form-control" id="' . $this->attr_name.'" name="' . $this->attr_name.'">' .$this->getCurVal() . '</textarea>';
}
function render_text( $crop = false ) {
$val = $this->getCurVal();
if ( $crop ) {
$val = substr(strip_tags($val),0, 100);
}
return html_entity_decode($val);
}
}
?>

View File

@ -0,0 +1,120 @@
<?php
class attr_tree extends attr {
var $linked_obj;
function __construct( $attr_name, $obj ) {
$this->attr_name = $attr_name;
$this->obj = $obj;
$full_type = $obj->attrs[$attr_name]['type'];
$lobj_name = $obj->obj_name;
$this->linked_obj = new cobject( $lobj_name, $this->obj->recursion_depth );
}
function getDBType() {
return "int(12)";
}
function render_text( $crop = false ) {
$id = $this->getCurVal();
$out = '';
$tpl = $this->obj->attrs[$this->attr_name]['templ'];
if ( $id ) {
$this->linked_obj->byId( $id );
$out = $this->linked_obj->assign( $tpl );
}
return $out;
}
function render_input() {
$db = $this->linked_obj->getDB();
$db2 = $db->q( $this->linked_obj->getSelect( $this->sql_where ) );
$id = $this->getCurVal();
$tpl = $this->obj->attrs[$this->attr_name]['templ'];
$out = '<select id="'.$this->attr_name.'" name="'.$this->attr_name.'" class="select form-control">';
$out .= '<option value="0">---</option>';
$out .= $this->r_subtree(0);
$out .= '</select>';
return $out;
}
function r_subtree( $cat, $level = 0 ) {
global $R, $core_db;
$db2 = $this->obj->getDB()->q( $this->obj->getSelect( ' AND `'.$this->attr_name.'` = "'.$cat.'" ORDER BY `title` ') );
while ( $db2->r() ) {
if ( $db2->f('id') == $this->getCurVal() ) {
$check = 'selected';
} else {
$check = '';
}
$out.= '<option '.$check.' value="'.$db2->f('id').'">';
for( $i=0; $i<$level; $i++ ) {
$out.= '&nbsp;&nbsp;&nbsp;&nbsp;';
}
$out .= '|-> ' . $db2->f('title');
$out.= '</option>';
$out .= $this->r_subtree($db2->f('id'), ($level+1));
}
return $out;
}
function getFilter( $sql_where = '' ) {
$db = $this->linked_obj->getDB();
$fname = $this->obj->obj_name . '_' . $this->attr_name;
if ( $this->obj->obj_name ) {
$db3 = $this->obj->getDB()->q( $this->obj->getSelectEx( ' DISTINCT(`'.$this->attr_name.'`) as `'.$this->attr_name.'` ', '' ) );
while ( $db3->nr() ) {
$uniq_ids[] = $db3->f($this->attr_name);
}
} else {
$uniq_ids = array();
}
if (!$_GET[$fname]) {
$tmp = array('<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'\'" selected>Все</option>');
$tmp_s = array('<a href="'._getCurl(array( $fname, 'curpage' )).'"><b>Все</b></a>');
} else {
$tmp = array('<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'\'">Все</option>');
$tmp_s = array('<a href="'._getCurl(array( $fname, 'curpage' )).'">Все</a>');
}
$db2 = $db->q( $this->linked_obj->getSelect( $sql_where) );
$c = 0;
while ( $db2->r() ) {
if ( $this->obj->obj_name && !in_array( $db2->f('id'), $uniq_ids ) ) continue;
$tpl = strip_tags( $this->getAttrTempl() );
$this->linked_obj->lRow($db2);
$tpl = $this->linked_obj->assign($tpl, true);
if ( strlen($tpl) > 100 ) $tpl = substr($tpl,0,100) . '...';
if ($_GET[$fname] != $db2->f('id')) {
$tplh = '<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'\'">' .$tpl . '</option>';
$tplh_s = '<a href="'._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'">' .$tpl . '</a>';
} else {
$tplh = '<option onClick="location.href=\''._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'\'" selected>' . $tpl . '</option>';
$tplh_s = '<a href="'._getCurl(array( $fname, 'curpage' )).'&' . $fname .'='.$db2->f('id').'"><b>' .$tpl . '</b></a>';
$ret['sql'] = " AND " . ($this->obj->obj_name?('`'.$this->obj->obj_name."`.`".$this->attr_name.'`'):($this->attr_name)) . " = '" . $db2->f('id') . "' " ;
}
$tmp[] = $tplh;
$tmp_s[] = $tplh_s;
$c++;
}
if ($c > 10 ) {
$ret['html'] = "<select class=\"form-control form-control-sm\">";
$ret['html'] .= implode('', $tmp);
$ret['html'] .= "</select>";
} else {
$ret['html'] .= implode(' | ', $tmp_s);
}
return $ret;
}
}
?>

View File

@ -0,0 +1,119 @@
<?php
class attr_tree_object extends attr {
var $linked_obj;
var $sql_where;
var $lobj_name;
function __construct( $attr_name, $obj ) {
$this->attr_name = $attr_name;
$this->obj = $obj;
$full_type = $obj->attrs[$attr_name]['type'];
$lobj_name = $obj->attrs[$attr_name]['templ'];
if ($lobj_name == "") {
$lobj_name = $obj->obj_name;
}
$this->lobj_name = $lobj_name;
}
function getDBType() {
return "varchar(255)";
}
function lPost() {
if (is_array($_POST[$this->attr_name])) {
$this->obj->set($this->attr_name,implode(",",$_POST[$this->attr_name]));
} else {
$this->obj->set($this->attr_name,$_POST[$this->attr_name]);
}
}
function getLinkedObj() {
if ( !$this->linked_obj ) {
$this->linked_obj = new cobject( $this->lobj_name, $this->obj->recursion_depth );
}
return $this->linked_obj;
}
function render_text( $crop = false ) {
$id = $this->getCurVal();
if (!$id) return '';
if ( $id ) $ids = explode( ",", $id );
$this->getLinkedObj()->byId( $id );
if ($this->getLinkedObj()->get('path_titles')) {
return $this->getLinkedObj()->assign('{path_titles}');
} elseif ($this->getLinkedObj()->get('path_ids')) {
$template_path = explode(',', $this->getLinkedObj()->get('path_ids'));
$path_data = array();
foreach( $template_path as $id ) {
$this->getLinkedObj()->byId( $id );
$path_data[] = $this->getLinkedObj()->assign('{title}');
}
return implode(' > ', $path_data);
} else {
return $this->getLinkedObj()->assign('{title}');
}
}
function render_input() {
$db = $this->getLinkedObj()->getDB();
$id = $this->getCurVal();
$tpl = $this->obj->attrs[$this->attr_name]['templ'];
$out = '<select name="'.$this->attr_name.'" id="'.$this->attr_name.'" class="form-control">';
$out .= '<option value="0">---</option>';
if ($this->sql_where) {
$out .= $this->r_subtree(intval($this->sql_where));
} else {
$out .= $this->r_subtree(0);
}
$out .= "</select>";
return $out;
}
function r_subtree( $cat, $level = 0 ) {
global $R, $core_db;
$cid = $this->getCurVal();
if ($cid) {
$cids = explode(",", $cid );
} else {
$cids = array();
}
$db2 = $this->getLinkedObj()->getDB()->q( $this->getLinkedObj()->getSelect( ' AND `parent_id` = "'.$cat.'" AND !`_sys_unvisible` ORDER BY `title` ') );
while ( $db2->r() ) {
if ( in_array( $db2->f('id'), $cids ) ) {
$check = 'selected';
} else {
$check = '';
}
$out.= '<option value="'.$db2->f('id').'" '.$check.'>';
for( $i=0; $i<$level; $i++ ) {
$out.= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
}
$out .= '|-> ' . $db2->f('title');
$out.= '</option>';
$out .= $this->r_subtree($db2->f('id'), ($level+1));
}
return $out;
}
function getFilter( $sql_where = '' ) {
return '';
}
}
?>

View File

@ -0,0 +1,33 @@
<?php
class attr_url extends attr {
function render_text( $crop = false ) {
return $this->getCurVal();
}
function render_input() {
if ( $this->getCurVal() && $this->obj->id ) {
return '<input id="' . $this->attr_name . '" type="hidden" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '">'.$this->getCurVal();
// return '<input id="' . $this->attr_name . '" type="text" name="' . $this->attr_name . '" value="' .$this->getCurVal() . '">';
} else {
return '<input id="' . $this->attr_name . '" type="text" name="' . $this->attr_name . '" class="form-control" value="' .$this->getCurVal() . '">'."
<script>
$(document).ready( function() {
$('#title').keyup( function() {
if ( $('#url').attr('type') == 'hidden' ) return true;
$('#url').val( translateStr( $('#title').val() ) + '-' + Math.floor((Math.random()*10000)+1));
return true;
});
});
</script>";
}
}
}
?>

View File

@ -0,0 +1,84 @@
<?php
class attr_userlist extends attr {
public $linked_obj;
public $sql_where;
public $lobj_name;
public function __construct($attr_name, $obj) {
$this->attr_name = $attr_name;
$this->obj = $obj;
$full_type = $obj->attrs[$attr_name]['type'];
$this->lobj_name = '_sys_users';
}
public function getDBType() {
return "varchar(255)";
}
public function getLinkedObj() {
if (!$this->linked_obj) {
$this->linked_obj = new cobject($this->lobj_name, $this->obj->recursion_depth);
}
return $this->linked_obj;
}
public function lPost() {
if (is_array($_POST[$this->attr_name])) {
$this->obj->set($this->attr_name, implode(",", $_POST[$this->attr_name]));
} else {
$this->obj->set($this->attr_name, $_POST[$this->attr_name]);
}
}
public function render_text($crop) {
$id = $this->getCurVal();
if ($id) {
$ids = explode(",", $id);
}
$outa = [];
if ($ids) {
foreach($ids as $id) {
$this->getLinkedObj()->byId($id); // Показывать удаленные
$outa[] = $this->getLinkedObj()->assign('{name}');
}
if ($outa) {
sort($outa);
}
}
return implode("; ", $outa);
}
public function render_input() {
global $core;
$db = $this->getLinkedObj()->getDB();
$addsql = $this->obj->attrs[$this->attr_name]['templ'];
$db2 = $db->q($this->getLinkedObj()->getSelect($this->sql_where . $addsql . ' ORDER BY `name`'));
$out = '';
$id = $this->getCurVal();
if ($id) {
$ids = explode(",", $id);
}
while ($db2->r()) {
$this->getLinkedObj()->lRow($db2);
$tt = $this->getLinkedObj()->assign(' {name}');
if ($ids && in_array($db2->f('id'), $ids)) {
$checked = 'checked';
} else {
$checked = '';
}
$out .= '<label><input type="checkbox" name="'.$this->attr_name.'[]" class="checkbox" ' . $checked . ' value="'.$db2->f('id').'">' . $tt . '</label><br>';
}
return $out;
}
}
?>

View File

@ -0,0 +1,79 @@
<?php
class attr_video extends attr {
function getDBType() {
return "int(12)";
}
function render_input() {
$html = '<input class="input" type="file" name="' . $this->attr_name . '"><br>(макс.: '.ini_get('upload_max_filesize').')';
$html .= '<input class="input" type="hidden" name="' . $this->attr_name . '" value="1">';
if ( $this->getCurVal() ) {
$html .= '<br><label><img src="img.php?id='.$this->obj->get($this->attr_name.'_preview').'" width="200"><br><input class="checkbox" type="checkbox" name="' . $this->attr_name . '_del" value="1"> Удалить</label>';
}
return $html;
}
function lPost() {
$tmpObj = new cobject( '_sys_files' );
$file = $_FILES[$this->attr_name];
$nn = md5(microtime(true));
if ($_POST[$this->attr_name . '_del']) {
$this->obj->set( $this->attr_name, 0 );
}
if (!$file['error']) {
$arr = explode('/', $file['type'] );
if ($arr[0] == 'video' || $arr[0] == 'application') {
if ( move_uploaded_file( $file['tmp_name'], _FILES_DIR_.$nn ) ) {
$tmpObj->set('filename', $nn );
$tmpObj->set('realname', $file['name'] );
$tmpObj->set('ext', $file['type'] );
$tmpObj->save();
$this->obj->set( $this->attr_name, $tmpObj->id );
symlink( _FILES_DIR_.$nn , _VIDEO_DIR_ . $tmpObj->id . '.flv');
if ( isset($this->obj->attrs[$this->attr_name.'_preview']) ) {
$str = "ffmpeg -i "._FILES_DIR_.$nn. " -an -ss 00:00:05 -an -r 1 -vframes 1 -y -f image2 -s ".$this->obj->attrs[$this->attr_name.'_preview']['templ']." " ._FILES_DIR_.$nn . "_pre.jpg";
system($str);
copy( _FILES_DIR_.$nn.'_pre.jpg' , _FILES_DIR_.$nn.'_pre' );
unlink( _FILES_DIR_.$nn.'_pre.jpg' );
$tmpObj->byId(0);
$tmpObj->set('filename', $nn.'_pre' );
$tmpObj->set('realname', $file['name'].'.jpg' );
$tmpObj->set('ext', 'image/jpeg' );
$tmpObj->save();
$this->obj->set($this->attr_name.'_preview', $tmpObj->id );
}
if ( isset($this->obj->attrs[$this->attr_name.'_full_preview']) ) {
$str = "ffmpeg -i "._FILES_DIR_.$nn. " -an -ss 00:00:05 -an -r 1 -vframes 1 -y -f image2 -s ".$this->obj->attrs[$this->attr_name.'_full_preview']['templ']." " ._FILES_DIR_.$nn . "_pre.jpg";
system($str);
copy( _FILES_DIR_.$nn.'_pre.jpg' , _FILES_DIR_.$nn.'_full_preview' );
unlink( _FILES_DIR_.$nn.'_pre.jpg' );
$tmpObj->byId(0);
$tmpObj->set('filename', $nn.'_full_preview' );
$tmpObj->set('realname', $file['name'].'.jpg' );
$tmpObj->set('ext', 'image/jpeg' );
$tmpObj->save();
$this->obj->set($this->attr_name.'_full_preview', $tmpObj->id );
}
}
}
}
}
function render_text( $crop = false ) {
if ($crop) {
$val = '<a href="file.php?id='.$this->getCurVal().'"><img src="img.php?id='.$this->obj->get($this->attr_name.'_preview').'" width="100">Скачать</a>';
} else {
if (!$this->getCurVal()) return '';
return $this->getCurVal();
}
return $val;
}
}
?>

View File

@ -0,0 +1,88 @@
<?php
class auth {
var $is_login = false;
var $user_id = 0;
var $user_obj;
var $sess_obj;
var $groups = array();
function __construct() {
global $core_db;
session_set_cookie_params(32140800,'/',_COOKIE_DOMAIN_); // Ñåññèÿ íà ãîä
session_start();
$sess_id = session_id();
$this->sess_obj = new cobject( '_sys_user_sessions' );
$this->user_obj = new cobject( '_sys_users' );
$db2 = $this->sess_obj->getDB()->q( $this->sess_obj->getSelect(' AND `session_id` = "'. db_escape_string($sess_id) . '" ' ) );
if ( $db2->nr() ) {
$this->_intAuth( $db2->f('user_id') );
} else {
$this->is_login = false;
}
}
function _intAuth( $user_id ) {
global $core_db;
$this->user_obj->byId($user_id);
if ($this->user_obj->id && !$this->user_obj->get('_sys_disabled') ) {
$this->is_login = true;
$this->user_id = $user_id;
if ( $this->user_obj->get('group') ) {
$this->groups = explode( ',', $this->user_obj->get('group') );
}
} else {
$this->do_logout();
}
}
function do_login( $user_id ) {
$this->do_logout();
$this->sess_obj->set('session_id', session_id() );
$this->sess_obj->set('user_id', $user_id );
$this->sess_obj->save();
$this->_intAuth($user_id);
}
function do_logout() {
$this->sess_obj->getDB()->q( 'DELETE FROM `_sys_user_sessions` WHERE `session_id` = "' . db_escape_string(session_id()) . '" ' );
$this->is_login = false;
$this->user_obj->byId( 0 );
$this->user_id = 0;
}
function is_login() {
return $this->is_login;
}
function get( $attr ) {
return $this->user_obj->get( $attr );
}
function sessGet($key) {
return $this->sessionData[$key];
}
function sessSet($key, $val) {
$this->sessionData[$key] = $val;
}
function saveSession() {
if ( $this->is_login ) {
$data = serialize($this->sessionData);
$this->user_obj->byId( $this->user_id );
if ( $data != $this->user_obj->get('session_data') ) {
$this->user_obj->set('session_data',$data);
$this->user_obj->save(false);
}
}
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,328 @@
<?php /** @noinspection UnknownInspectionInspection */
/** @noinspection PhpMissingParamTypeInspection */
/** @noinspection ReturnTypeCanBeDeclaredInspection */
/** @noinspection PhpMissingReturnTypeInspection */
/** @noinspection TypeUnsafeComparisonInspection */
/** @noinspection PhpUnused */
/** @noinspection DuplicatedCode */
namespace eftec\bladeone;
use Exception;
use function fclose;
use function file_put_contents;
use function filemtime;
use function filesize;
use function fopen;
use function fwrite;
use function is_array;
use function is_object;
use function ob_get_contents;
use function print_r;
use function strlen;
use function substr;
use function time;
/**
* trait BladeOneCache
* Copyright (c) 2016 Jorge Patricio Castro Castillo MIT License. Don't delete this comment, its part of the license.
* Extends the tags of the class BladeOne. Its optional
* It adds the next tags to the template
* <code>
* @ cache([cacheid],[duration=86400]). The id is optional. The duration of the cache is in seconds
* // content here
* @ endcache()
* </code>
* It also adds a new function (optional) to the business or logic layer
* <code>
* if ($blade->cacheExpired('hellocache',1,5)) { //'helloonecache' =template, =1 id cache, 5=duration (seconds)
* // cache expired, so we should do some stuff (such as read from the database)
* }
* </code>
*
* @package BladeOneCache
* @version 3.42 2020-04-25
* @link https://github.com/EFTEC/BladeOne
* @author Jorge Patricio Castro Castillo <jcastro arroba eftec dot cl>
*/
trait BladeOneCache
{
protected $curCacheId = 0;
protected $curCacheDuration = 0;
protected $curCachePosition = 0;
protected $cacheRunning = false;
protected $cachePageRunning = false;
protected $cacheLog;
/**
* @var array avoids to compare the file different times. It also avoids race conditions.
*/
private $cacheExpired = [];
/**
* @var string=['get','post','getpost','request',null][$i]
*/
private $cacheStrategy;
/** @var array|null */
private $cacheStrategyIndex;
/**
* @return null|string $cacheStrategy=['get','post','getpost','request',null][$i]
*/
public function getCacheStrategy()
{
return $this->cacheStrategy;
}
/**
* It sets the cache log. If not cache log then it does not generates a log file<br>
* The cache log stores each time a template is creates or expired.<br>
*
* @param string $file
*/
public function setCacheLog($file)
{
$this->cacheLog=$file;
}
public function writeCacheLog($txt, $nivel)
{
if (!$this->cacheLog) {
return; // if there is not a file assigned then it skips saving.
}
$fz = @filesize($this->cacheLog);
if (is_object($txt) || is_array($txt)) {
$txt = print_r($txt, true);
}
// Rewrite file if more than 100000 bytes
$mode=($fz > 100000) ? 'w':'a';
$fp = fopen($this->cacheLog, $mode);
if ($fp === false) {
return;
}
switch ($nivel) {
case 1:
$txtNivel='expired';
break;
case 2:
$txtNivel='new';
break;
default:
$txtNivel='other';
}
$txtarg=json_encode($this->cacheUniqueGUID(false));
fwrite($fp, date('c') . "\t$txt\t$txtNivel\t$txtarg\n");
fclose($fp);
}
/**
* It sets the strategy of the cache page.
*
* @param null|string $cacheStrategy =['get','post','getpost','request',null][$i]
* @param array|null $index if null then it reads all indexes. If not, it reads a indexes.
*/
public function setCacheStrategy($cacheStrategy, $index = null)
{
$this->cacheStrategy = $cacheStrategy;
$this->cacheStrategyIndex = $index;
}
/**
* It obtains an unique GUID based in:<br>
* <b>get</b>= parameters from the url<br>
* <b>post</b>= parameters sends via post<br>
* <b>getpost</b> = a mix between get and post<br>
* <b>request</b> = get, post and cookies (including sessions)<br>
* MD5 could generate colisions (2^64 = 18,446,744,073,709,551,616) but the end hash is the sum of the hash of
* the page + this GUID.
*
* @param bool $serialize if true then it serializes using md5
* @return string
*/
private function cacheUniqueGUID($serialize = true)
{
switch ($this->cacheStrategy) {
case 'get':
$r = $_GET;
break;
case 'post':
$r = $_POST;
break;
case 'getpost':
$arr = array_merge($_GET, $_POST);
$r = $arr;
break;
case 'request':
$r = $_REQUEST;
break;
default:
$r = null;
}
if ($this->cacheStrategyIndex === null || !is_array($r)) {
$r= serialize($r);
} else {
$copy=[];
foreach ($r as $key => $item) {
if (in_array($key, $this->cacheStrategyIndex, true)) {
$copy[$key]=$item;
}
}
$r=serialize($copy);
}
return $serialize===true ? md5($r): $r;
}
public function compileCache($expression)
{
// get id of template
// if the file exists then
// compare date.
// if the date is too old then re-save.
// else
// save for the first time.
return $this->phpTag . "echo \$this->cacheStart$expression; if(!\$this->cacheRunning) { ?>";
}
public function compileEndCache($expression)
{
return $this->phpTag . "} // if cacheRunning\necho \$this->cacheEnd$expression; ?>";
}
/**
* It get the filename of the compiled file (cached). If cache is not enabled, then it
* returns the regular file.
*
* @param string $view
* @return string The full filename
*/
private function getCompiledFileCache($view)
{
$id = $this->cacheUniqueGUID();
if ($id !== null) {
return str_replace($this->compileExtension, '_cache' . $id
. $this->compileExtension, $this->getCompiledFile($view));
}
return $this->getCompiledFile($view);
}
/**
* run the blade engine. It returns the result of the code.
*
* @param string $view The name of the cache. Ex: "folder.folder.view" ("/folder/folder/view.blade")
* @param array $variables An associative arrays with the values to display.
* @param int $ttl time to live (in second).
* @return string
* @throws Exception
*/
public function runCache($view, $variables = [], $ttl = 86400)
{
$this->cachePageRunning = true;
$cacheStatus=$this->cachePageExpired($view, $ttl);
if ($cacheStatus!==0) {
$this->writeCacheLog($view, $cacheStatus);
$this->cacheStart('_page_', $ttl);
$content = $this->run($view, $variables); // if no cache, then it runs normally.
$this->fileName = $view; // sometimes the filename is replaced (@include), so we restore it
$this->cacheEnd($content); // and it stores as a cache paged.
} else {
$content = $this->getFile($this->getCompiledFileCache($view));
}
$this->cachePageRunning = false;
return $content;
}
/**
* Returns true if the block cache expired (or doesn't exist), otherwise false.
*
* @param string $templateName name of the template to use (such hello for template hello.blade.php)
* @param string $id (id of cache, optional, if not id then it adds automatically a number)
* @param int $cacheDuration (duration of the cache in seconds)
* @return int 0=cache exists, 1= cache expired, 2=not exists, string= the cache file (if any)
*/
public function cacheExpired($templateName, $id, $cacheDuration)
{
if ($this->getMode() & 1) {
return 2; // forced mode, hence it always expires. (fast mode is ignored).
}
$compiledFile = $this->getCompiledFile($templateName) . '_cache' . $id;
return $this->cacheExpiredInt($compiledFile, $cacheDuration);
}
/**
* It returns true if the whole page expired.
*
* @param string $templateName
* @param int $cacheDuration is seconds.
* @return int 0=cache exists, 1= cache expired, 2=not exists, string= the cache content (if any)
*/
public function cachePageExpired($templateName, $cacheDuration)
{
if ($this->getMode() & 1) {
return 2; // forced mode, hence it always expires. (fast mode is ignored).
}
$compiledFile = $this->getCompiledFileCache($templateName);
return $this->CacheExpiredInt($compiledFile, $cacheDuration);
}
/**
* This method is used by cacheExpired() and cachePageExpired()
*
* @param string $compiledFile
* @param int $cacheDuration is seconds.
* @return int|mixed 0=cache exists, 1= cache expired, 2=not exists, string= the cache content (if any)
*/
private function cacheExpiredInt($compiledFile, $cacheDuration)
{
if (isset($this->cacheExpired[$compiledFile])) {
// if the information is already in the array then returns it.
return $this->cacheExpired[$compiledFile];
}
$date = @filemtime($compiledFile);
if ($date) {
if ($date + $cacheDuration < time()) {
$this->cacheExpired[$compiledFile] = 1;
return 2; // time-out.
}
} else {
$this->cacheExpired[$compiledFile] = 2;
return 1; // no file
}
$this->cacheExpired[$compiledFile] = 0;
return 0; // cache active.
}
public function cacheStart($id = '', $cacheDuration = 86400)
{
$this->curCacheId = ($id == '') ? ($this->curCacheId + 1) : $id;
$this->curCacheDuration = $cacheDuration;
$this->curCachePosition = strlen(ob_get_contents());
if ($this->cachePageRunning) {
$compiledFile = $this->getCompiledFileCache($this->fileName);
} else {
$compiledFile = $this->getCompiledFile() . '_cache' . $this->curCacheId;
}
if ($this->cacheExpired('', $id, $cacheDuration) !==0) {
$this->cacheRunning = false;
} else {
$this->cacheRunning = true;
$content = $this->getFile($compiledFile);
echo $content;
}
}
public function cacheEnd($txt = null)
{
if (!$this->cacheRunning) {
$txt = $txt ?? substr(ob_get_contents(), $this->curCachePosition);
if ($this->cachePageRunning) {
$compiledFile = $this->getCompiledFileCache($this->fileName);
} else {
$compiledFile = $this->getCompiledFile() . '_cache' . $this->curCacheId;
}
file_put_contents($compiledFile, $txt);
}
$this->cacheRunning = false;
}
}

View File

@ -0,0 +1,160 @@
<?php
namespace eftec\bladeone;
use Redis;
use function class_exists;
use function file_put_contents;
use function filemtime;
use function ob_get_contents;
use function strlen;
use function substr;
use function time;
/**
* trait BladeOneCacheRedis
* Copyright (c) 2016 Jorge Patricio Castro Castillo MIT License. Don't delete this comment, its part of the license.
* Extends the tags of the class BladeOne. Its optional
* It adds the next tags to the template
* <code>
* @ cache([cacheid],[duration=86400]). The id is optional. The duration of the cache is in seconds
* // content here
* @ endcache()
* </code>
* It also adds a new function (optional) to the business or logic layer
* <code>
* if ($blade->cacheExpired('hellocache',1,5)) { //'helloonecache' =template, =1 id cache, 5=duration (seconds)
* // cache expired, so we should do some stuff (such as read from the database)
* }
* </code>
*
* @package BladeOneCacheRedis
* @version 0.1 2017-12-15 NOT YET IMPLEMENTED, ITS A WIP!!!!!!!!
* @link https://github.com/EFTEC/BladeOne
* @author Jorge Patricio Castro Castillo <jcastro arroba eftec dot cl>
*/
const CACHEREDIS_SCOPEURL = 1;
trait BladeOneCacheRedis
{
protected $curCacheId = 0;
protected $curCacheDuration = "";
protected $curCachePosition = 0;
protected $cacheRunning = false;
/** @var \Redis $redis */
protected $redis;
protected $redisIP = '127.0.0.1';
protected $redisPort = 6379;
protected $redisTimeOut = 2.5;
protected $redisConnected = false;
protected $redisNamespace = 'bladeonecache:';
protected $redisBase = 0;
private $cacheExpired = []; // avoids to compare the file different times.
//<editor-fold desc="compile">
public function compileCache($expression)
{
// get id of template
// if the file exists then
// compare date.
// if the date is too old then re-save.
// else
// save for the first time.
return $this->phpTag . "echo \$this->cacheStart{$expression}; if(!\$this->cacheRunning) { ?>";
}
public function compileEndCache($expression)
{
return $this->phpTag . "} // if cacheRunning\necho \$this->cacheEnd{$expression}; ?>";
}
//</editor-fold>
public function connect($redisIP = null, $redisPort = null, $redisTimeOut = null)
{
if ($this->redisConnected) {
return true;
}
if (!class_exists('Redis')) {
return false; // it requires redis.
}
if ($redisIP !== null) {
$this->redisIP = $redisIP;
$this->redisPort = $redisPort;
$this->redisTimeOut = $redisTimeOut;
}
$this->redis = new Redis();
// 2.5 sec timeout.
$this->redisConnected = $this->redis->connect($this->redisIP, $this->redisPort, $this->redisTimeOut);
return $this->redisConnected;
}
/**
* Returns true if the cache expired (or doesn't exist), otherwise false.
*
* @param string $templateName name of the template to use (such hello for template hello.blade.php)
* @param string $id (id of cache, optional, if not id then it adds automatically a number)
* @param int $scope scope of the cache.
* @param int $cacheDuration (duration of the cache in seconds)
* @return bool (return if the cache expired)
*/
public function cacheExpired($templateName, $id, $scope, $cacheDuration)
{
if ($this->getMode() & 1) {
return true; // forced mode, hence it always expires. (fast mode is ignored).
}
$compiledFile = $this->getCompiledFile($templateName) . '_cache' . $id;
if (isset($this->cacheExpired[$compiledFile])) {
// if the information is already in the array then returns it.
return $this->cacheExpired[$compiledFile];
}
$date = @filemtime($compiledFile);
if ($date) {
if ($date + $cacheDuration < time()) {
$this->cacheExpired[$compiledFile] = true;
return true; // time-out.
}
} else {
$this->cacheExpired[$compiledFile] = true;
return true; // no file
}
$this->cacheExpired[$compiledFile] = false;
return false; // cache active.
}
public function cacheStart($id = "", $cacheDuration = 86400)
{
$this->curCacheId = ($id == "") ? ($this->curCacheId + 1) : $id;
$this->curCacheDuration = $cacheDuration;
$this->curCachePosition = strlen(ob_get_contents());
$compiledFile = $this->getCompiledFile() . '_cache' . $this->curCacheId;
if ($this->cacheExpired('', $id, $cacheDuration)) {
$this->cacheRunning = false;
} else {
$this->cacheRunning = true;
$content = $this->getFile($compiledFile);
echo $content;
}
// getFile($fileName)
}
public function cacheEnd()
{
if (!$this->cacheRunning) {
$txt = substr(ob_get_contents(), $this->curCachePosition);
$compiledFile = $this->getCompiledFile() . '_cache' . $this->curCacheId;
file_put_contents($compiledFile, $txt);
}
$this->cacheRunning = false;
}
private function keyByScope($scope)
{
$key = '';
if ($scope && CACHEREDIS_SCOPEURL) {
$key .= $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
}
}
}

View File

@ -0,0 +1,59 @@
<?php /** @noinspection ReturnTypeCanBeDeclaredInspection */
/** @noinspection PhpMissingReturnTypeInspection */
/** @noinspection UnknownInspectionInspection */
/** @noinspection PhpUnused */
namespace eftec\bladeone;
/*
* Its an example of a custom set of functions for bladeone.
* in examples/TestCustom.php there is a working example
*/
use function array_pop;
trait BladeOneCustom
{
private $customItem = []; // indicates the type of the current tag. such as select/selectgroup/etc.
//<editor-fold desc="compile function">
/**
* Usage @panel('title',true,true).....@endpanel()
*
* @param $expression
* @return string
*/
protected function compilePanel($expression)
{
$this->customItem[] = 'Panel';
return $this->phpTag . "echo \$this->panel$expression; ?>";
}
protected function compileEndPanel()
{
$r = @array_pop($this->customItem);
if ($r === null) {
$this->showError('@endpanel', 'Missing @compilepanel or so many @compilepanel', true);
}
return ' </div></section><!-- end panel -->'; // we don't need to create a function for this.
}
//</editor-fold>
//<editor-fold desc="used function">
protected function panel($title = '', $toggle = true, $dismiss = true)
{
return "<section class='panel'>
<header class='panel-heading'>
<div class='panel-actions'>
" . (($toggle) ? "<a href='#' class='panel-action panel-action-toggle' data-panel-toggle></a>" : '') . '
' . (($dismiss) ? "<a href='#' class='panel-action panel-action-dismiss' data-panel-dismiss></a>" : '') . "
</div>
<h2 class='panel-title'>$title</h2>
</header>
<div class='panel-body'>";
}
//</editor-fold>
}

View File

@ -0,0 +1,388 @@
<?php
class cat {
var $cat;
var $cat_name;
var $module;
var $data;
var $templ = 'index.htm';
var $xml = 'index.xml';
var $path;
var $path_name;
var $breadcrumbs = array();
var $access;
var $meta_keywords = array();
var $meta_description = '';
var $add_headers = array();
function __construct() {
global $core_db, $db;
$this->cat = addslashes($_POST['cat']);
if ( !$this->cat )
$this->cat = addslashes($_GET['cat']);
if ( !$this->cat ) $this->cat = 'index';
$cat_obj = new cobject( __REAL_CAT_OBJ_ );
$db2 = $core_db->q( $cat_obj->getSelect( ' AND `cat_id` = "' . $this->cat . '"' ) );
if ( $db2->r() ) {
$cat_obj->lRow( $db2 );
$this->module = $cat_obj->get('module');
$this->cat_name = $cat_obj->get('cat_name');
$this->data = $this->dataParse(htmlspecialchars_decode($cat_obj->get('data')));
if (!$cat_obj->get('xml') ) {
$this->xml = $this->searchXml( $cat_obj->get('parent_cat') );
} else {
$this->xml = $cat_obj->get('xml');
}
$this->path = $this->getPath();
if ( $cat_obj->get('meta_keywords') ) {
$this->addKeywords( $cat_obj->get('meta_keywords') );
}
if ( $cat_obj->get('meta_description') ) {
$this->setDescription( $cat_obj->get('meta_description') );
}
if ( $cat_obj->get('access_group') ) {
$this->access = explode( ",", $cat_obj->get('access_group') );
}
if (!$this->module) {
$this->module = 'line_menu.php';
$this->data = array('root' => $this->cat );
}
} else {
header("HTTP/1.1 404 Not Found");
if (defined('_ADMINKA_')) {
header("Location: "._SITE_ROOT_);
} else {
header("Location: "._SITE_ROOT_."404");
}
die();
/*
$this->module = 'loginbox.php';
$this->cat_name = 'Авторизация';
$this->path = $this->getPath();
$this->xml = 'login.xml';
*/
}
if (!$this->xml) {
cdie('XML не определена');
}
}
function checkAccess() {
global $auth;
if ( !$this->access ) return true;
if ( $auth->user_id == _ROOT_USER_ID ) return true;
$acc = false;
foreach( $auth->groups as $v ) {
if (in_array( $v, $this->access ) ) {
$acc = true;
}
}
return $acc;
}
function dataParse( $data = "" ) {
preg_match_all( '/\$(.*?)=(.*?);/', $data, $r );
foreach( $r[1] as $k => $var ) {
$var = trim($var);
$ret[$var] = trim($r[2][$k]);
}
return $ret;
}
function searchXml( $cat ) {
global $core_db;
$cat_obj = new cobject( __REAL_CAT_OBJ_ );
$db2 = $core_db->q( $cat_obj->getSelect( ' AND `cat_id` = "' . $cat . '" ' ) );
$db2->r();
if (!$db2->f('xml') ) {
return $this->searchXml( $db2->f('parent_cat') );
} else {
return $db2->f('xml');
}
}
function render() {
/* load module */
global $R;
if ( !$this->checkAccess() ) {
$this->module = 'loginbox.php';
$this->cat_name = 'Авторизация';
$this->path = $this->getPath();
$this->xml = 'login.xml';
}
if ( $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest' ) {
// Не выполняем всю движку, только модуль и сразу возвращаемся
if (substr($this->module,-4) == '.php' ) {
$module = substr($this->module,0,-4);
}
require_once( _BASE_DIR . 'modules/' . $module .'.php' );
$body_module = new $module( $this->data );
if ( $body_module->_sys_no_load ) return;
return $R->clear($body_module->render( 'body', true));
}
$this->parseXml();
$this->setModule( 'body', $this->module, $this->data );
if ( $this->delayed_modules ) {
foreach( $this->delayed_modules as $arr ) {
$this->setModule( $arr['tpl'], $arr['module'], $arr['data'] );
}
}
$this->out = $R->set('meta_keywords', implode(', ', $this->meta_keywords), $this->out );
$this->out = $R->set('meta_description', $this->meta_description, $this->out );
if ($this->cat != 'index' ) {
$this->out = $R->set('breadcrumbs', $this->r_breadcrumbs(), $this->out );
}
/*
$this->out = $R->set('auto_title', implode(" / ", $this->path_name), $this->out );
*/
$this->out = $R->set('auto_title', $this->path_name[0], $this->out );
if ( defined('NOINDEX') ) {
$this->addHeaders('<meta name="robots" content="noindex,nofollow">');
}
$this->out = $R->set('add_headers', implode("\n", $this->add_headers), $this->out );
return $R->clear( $this->out );
}
function r_breadcrumbs() {
global $R;
$tpl = $R->getTpl( 'breadcrumbs.htm', 'body' );
$tplr = $R->getTpl( 'breadcrumbs.htm', 'row' );
$tpls = $R->getTpl( 'breadcrumbs.htm', 'sep' );
$tpll = $R->getTpl( 'breadcrumbs.htm', 'last_row' );
$first_yes = false;
if (!$this->breadcrumbs ) {
foreach( $this->path as $k => $v ) {
if ($v != 'index') {
$tit = $this->path_name[$k];
$this->breadcrumbs[$v] = $tit;
} else {
$tit = $this->path_name[$k];
$this->breadcrumbs[''] = $tit;
$first_yes = true;
}
}
$this->breadcrumbs = array_reverse( $this->breadcrumbs, true );
}
$cnt = @count( $this->breadcrumbs );
if (!$first_yes ) {
$tta[] = $R->set('url', '', $R->set('title', end($this->path_name), $tplr) );
}
foreach( $this->breadcrumbs as $k => $v ) {
$i++;
if ( $i == $cnt ) {
$tplr = $tpll;
}
if ($i == ($cnt-1) ) {
$tpl = $R->set('parent_url', $k, $tpl );
$tpl = $R->set('parent_title', $v, $tpl);
}
$tt = $R->set('url', $k, $tplr );
$tt = $R->set('title', $v, $tt);
$tta[] = $tt;
}
if ($cnt == 1 ) {
$tpl = $R->set('parent_url', '/', $tpl );
$tpl = $R->set('parent_title', 'Главная', $tpl);
}
$tpl = $R->set('rows', implode( $tpls, $tta ), $tpl );
return $R->clear( $tpl );
}
function setModule( $templ, $module, $data = array() ) {
global $R, $statistica;
if ( !$module ) return;
if (substr($module,-4) == '.php' ) {
$module = substr($module,0,-4);
}
require_once( _BASE_DIR . 'modules/' . $module .'.php' );
$tmptime = microtime( true );
$body_module = new $module( $data );
if ( $body_module->_sys_no_load ) return;
if ($templ == 'body') {
global $blade;
$blade->share('module', $body_module);
}
$this->out = $R->set( $templ, $body_module->render( $templ ), $this->out );
$statistica['modules'][$module] = microtime( true ) - $tmptime;
}
function parseXml($exec_modules = true) {
global $R;
$xml = simplexml_load_file( _BASE_DIR . 'xml/'.$this->xml );
$xml = (Array)$xml;
$this->templ = $xml['@attributes']['filename'];
if ($_GET['frame_mode'] && $xml['@attributes']['frame_filename']) {
$this->templ = $xml['@attributes']['frame_filename'];
}
if ( !$this->templ ) cdie( 'Не указан файл шаблона в xml' );
unset($xml['@attributes']);
$this->out = $R->getTpl( $this->templ );
foreach( $xml as $templ_set => $module_data ) {
if ( is_object( $module_data )) {
foreach( $module_data as $module => $attrs ) {
$delay = false;
$attrs = (Array)$attrs;
$data = Array();
if (isset( $attrs['@attributes'] ) ) {
foreach( $attrs['@attributes'] as $k => $v ) {
$data[$k] = $v;
if ($k == 'delay' && $v == 'true' ) {
$delay = true;
}
}
}
if ($delay ) {
$this->delayed_modules[] = array('tpl' => $templ_set, 'module' => $module, 'data' => $data );
} else {
$this->setModule( $templ_set, $module, $data );
}
}
}
}
}
function getPath() {
global $core_db;
$cat_obj = new cobject( __REAL_CAT_OBJ_ );
$db2 = $core_db->q( $cat_obj->getSelect( ' AND `cat_id` = "' . $this->cat . '"' ) );
$db2->r();
$parent_cat = $db2->f('parent_cat');
if ( !$db2->f('_sys_unvisible') ) {
$path[] = $this->cat;
$this->path_name[] = $db2->f('cat_name');
}
while( $parent_cat ) {
$i++;
$db2 = $core_db->q( $cat_obj->getSelect( ' AND `cat_id` = "' . $parent_cat . '"' ) );
$db2->r();
if ( !$db2->f('_sys_unvisible') ) {
$path[] = $parent_cat;
$this->path_name[] = $db2->f('cat_name');
}
$parent_cat = $db2->f('parent_cat');
if ($i > 10 ) cdie('Больше 10 вложений в пути.');
}
return $path;
}
function addKeywords($words) {
if ($words) {
$this->meta_keywords[] = $words;
}
}
function addTitle($words) {
global $url_arr;
if ($words) {
array_unshift( $this->path_name, $words );
array_unshift( $this->path, implode('/', $url_arr ) );
return true;
}
return false;
}
function addCurTitle($words) {
if ($words) {
$this->path_name[0] .= ' ' .trim( $words ) ;
return true;
}
return false;
}
function setKeywords($words) {
if ($words) {
$this->meta_keywords = explode(',', $words );
return true;
}
return false;
}
function setDescription($words) {
if ($words) {
$this->meta_description = $words;
return true;
}
return false;
}
function setPath($path) {
if ($path) {
$this->breadcrumbs = $path;
return true;
}
return false;
}
function addPath($url, $title) {
if ( $url || $title ) {
$this->breadcrumbs[$url] = $title;
return true;
}
return false;
}
function addHeaders( $title ) {
if (!in_array($title, $this->add_headers ) ) {
$this->add_headers[] = $title;
}
}
}
?>

View File

@ -0,0 +1,124 @@
<?php
class db {
var $database;
var $r;
var $host;
var $user;
var $pass;
var $dbname;
var $lastRow;
function connect( $host, $user, $pass, $dbname, $db_create = false ) {
$this->host = $host;
$this->user = $user;
$this->pass = $pass;
$this->dbname = $dbname;
$this->database = mysqli_connect($host,$user,$pass,$dbname);
if ( !$this->database ) {
die('Mysql server fail');
}
}
function new_db() {
$db = clone $this;
$db->connect($this->host, $this->user, $this->pass, $this->dbname);
return $db;
}
function q( $sql ) {
global $statistica;
$statistica['q_count']++;
$statistica['sqls'][] = $sql;
$starttime = microtime( true );
if (!($result = mysqli_query($this->database, $sql) ) ) {
if (php_sapi_name()==='cli') {
echo '/* MYSQL_ERROR */ ' . PHP_EOL;
echo mysqli_error($this->database);
echo PHP_EOL;
die();
}
if ( _DEBUG != true ) {
header("HTTP/1.1 503 Service Unavailable", true, 503);
header("Retry-After: 3600");
$data = file_get_contents(_SHOP_DIR . 'blocker/index.html');
echo $data;
die();
}
//die('error');
echo "<xmp>";
debug_print_backtrace();
echo "</xmp>";
die(mysqli_error($this->database) . "<br>" . $sql );
} else {
$endtime = microtime( true );
$statistica['query_time'] += ($endtime - $starttime);
$statistica['sql_time'][] = ($endtime - $starttime);
$this->r = $result;
return clone $this;
}
}
function r() {
$row = mysqli_fetch_assoc($this->r);
if ( $row ) {
$this->lastRow = $row;
return true;
} else {
return false;
}
}
function nr() {
return $this->r();
}
function f( $key ) {
return $this->lastRow[$key];
}
function insert_id() {
return mysqli_insert_id($this->database);
}
function affected_rows() {
return mysqli_affected_rows($this->database);
}
function close() {
mysqli_close( $this->database );
}
public function fetchAll() {
return mysqli_fetch_all($this->r, MYSQLI_ASSOC);
}
}
$core_db = new db();
function db_escape_string($str = "") {
global $core_db;
return mysqli_real_escape_string($core_db->database, $str);
}
function db_real_escape_string($str = "") {
return db_escape_string($str);
}
function mysql_real_escape_string($str = "") {
return db_escape_string($str);
}
?>

View File

@ -0,0 +1,45 @@
<?php
class DBFileSystem {
static function uploadFile($filename, $is_private, $mimeType = '', $realFileName = '') {
$hashfile = md5_file($filename);
/*
* Логика такая. Чтобы не плодить много одинаковых файлов -
* имя файла берётся из хеша его содержимого
* для одинаковых файлов будет одинаковое имя
* при сохранении смотрим - если такой файл в системе уже есть - не создаем новый
**************************************************/
$fname = $hashfile;
/*
* Создаем структуру директорий для сохранения файла
*/
$fpath = substr($fname,0,2);
$fpath2 = substr($fname,2,2);
@mkdir( _FILES_DIR_ . $fpath . '/' . $fpath2, 0777, true );
$fname = $fpath .'/' . $fpath2 . '/' . $fname;
$fobj = new cobject('_sys_files');
$fobj->set('filename', $fname );
$fobj->set('ext', $mimeType);
$fobj->set('realname', $realFileName);
$fobj->set('private', $is_private);
$fobj->set('hash', $hashfile);
$fobj->save();
if (!file_exists(_FILES_DIR_ . $fname) ) {
rename($filename, _FILES_DIR_ . $fname);
} else {
unlink($filename);
}
return $fobj->id;
}
}
?>

View File

@ -0,0 +1,56 @@
<?php
class filter {
var $html = array();
var $sql;
var $obj;
var $add_sql = array();
var $filter_columns = array();
function filter( $obj_name ) {
$this->obj = new cobject ( $obj_name );
}
function add_filter( $attr_name ) {
$this->filter_columns[] = $attr_name;
}
function parse() {
foreach( $this->obj->attrs as $name => $attr ) {
if (!empty( $this->filter_columns ) && !in_array($name, $this->filter_columns ) ) continue;
$arr = $attr['attr_obj']->getFilter($this->add_sql[$name]);
if ($arr['html']) {
$this->sql .= $arr['sql'];
$this->html[$name] = '<div class="form-group mb-1 form-sm"><label class="mb-0 small text-muted">'.($this->descs[$name]?$this->descs[$name]:$attr['desc']) .'</label><div>' . $arr['html'] .'</div></div>';
}
}
}
function add_sql( $attr_name, $sql_where ) {
$this->add_sql[$attr_name] = $sql_where;
}
function set_desc( $attr_name, $sql_where ) {
$this->descs[$attr_name] = $sql_where;
}
function getHTML($attrs = array()) {
if (empty($attrs) ) return implode("",$this->html);
$ret = array();
foreach( $attrs as $k ) {
if ( $this->html[$k] )
$ret[] = $this->html[$k];
}
return implode("<br>",$ret);
}
function getSQL() {
return $this->sql;
}
}
?>

View File

@ -0,0 +1,236 @@
<?php
class form {
var $obj;
var $templ = "attrs/form.htm";
var $form = array();
var $hidden_vars = array();
var $title = '';
var $parsed = false;
function __construct( $obj ) {
global $cat;
$this->obj = $obj;
}
function setTempl( $filename ) {
$this->templ = $filename;
}
function setTitle( $title ) {
$this->title = $title;
}
function set_sql_where( $attr_name, $sql_where ) {
$this->obj->attrs[$attr_name]['attr_obj']->sql_where = $sql_where;
}
function _parse() {
if ($this->parsed) return;
foreach ( $this->obj->attrs as $k => $attr ) {
$this->form[$k]['title'] = $attr['desc'];
if ( $attr['hide'] || in_array( $k, $this->obj->force_hidden ) ) {
$this->form[$k]['html'] = '';
} else {
$this->form[$k]['html'] = $attr['attr_obj']->render_input();
}
$this->form[$k]['mand'] = $attr['mand'];
$this->form[$k]['hidden'] = $attr['hide'];
$this->form[$k]['error'] = $this->obj->errors[$k];
}
$this->parsed = true;
}
function _html( $act = "save_edit" ) {
global $R;
$tpl = $R->getTpl( $this->templ, 'body' );
$tplr = $R->getTpl( $this->templ, 'row' );
$tplr_chbox = $R->getTpl( $this->templ, 'row_checkbox' );
$tplm = $R->getTpl( $this->templ, 'mand' );
foreach( $this->form as $k => $v ) {
if ( in_array( $k, $this->obj->force_hidden ) ) continue;
if ( $v['hidden'] || ( in_array($k, $this->hidden_vars)) ) {
$tt = '<input type="hidden" name="' . $k . '" value="' . $this->obj->get( $k ) . '">';
$tpl = $R->parse( 'hidden_attrs', $tt, $tpl );
} else {
$tt = $tplr;
if ($this->obj->attrs[$k]['type'] == 'checkbox' ) {
$tt = $tplr_chbox;
}
$tt = $R->set( 'attr_title', $v['title'], $tt );
$tt = $R->set( 'attr_html', $v['html'], $tt );
$tt = $R->set( 'attr_name', $k, $tt );
if ( $v['mand'] ) {
$tt = $R->set( 'attr_mand', $tplm, $tt );
} else {
$tt = $R->set( 'attr_mand', '' ,$tt );
}
if ( $v['error'] ) {
$tt = $R->set( 'attr_error', '<div>'.$v['error'].'</div>', $tt );
} else {
$tt = $R->set( 'attr_error', '', $tt );
}
$tpl = $R->parse( 'form_rows', $tt, $tpl );
}
}
if ( $this->title ) {
$tplt = $R->getTpl( $this->templ, 'th' );
$tplt = $R->set('title', $this->title, $tplt );
$tpl = $R->set('title_row', $tplt, $tpl );
}
$tpl = $R->set( 'id', $this->obj->id, $tpl );
$tpl = $R->set( 'send_act', $act, $tpl );
return $R->clear( $tpl );
}
function render( $act = "save_edit" ) {
$this->_parse();
return $this->_html( $act );
}
function set_hidden( $attr_name ) {
$this->hidden_vars[] = $attr_name;
}
/**
* Получаем HTML код артибута
* @param string $fieldName имя атрибута
* @return html
*/
function fieldHTML($fieldName) {
$this->_parse();
$arr = $this->form[$fieldName];
if ( $arr['hidden'] ) {
return '<input type="hidden" name="'.$attr_name.'" value="'.$this->obj->get($attr_name).'">';
} else {
return $arr['html'];
$tpl = $R->set( $attr_name .'_title', $arr['title'].($arr['mand']?'<span class="error">*</span>':''), $tpl );
$tpl = $R->set( $attr_name .'_html', $arr['html'], $tpl );
$tpl = $R->set( $attr_name .'_error', '<div class="error">'.$this->obj->errors[$attr_name].'</div>', $tpl );
}
}
/**
* Имя атрибута для формы
* @param string $fieldName имя атрибута
* @return html
*/
function fieldTitle($fieldName) {
$this->_parse();
return $arr['title'].($arr['mand']?'<span class="error">*</span>':'');
}
/**
* Ошибка атрибута для формы
* @param string $fieldName имя атрибута
* @return html
*/
function fieldError($fieldName) {
$this->_parse();
if ( isset($this->obj->errors[$attr_name]) && $this->obj->errors[$attr_name] != "") {
return '<div class="error">'.$this->obj->errors[$attr_name].'</div>';
}
return '';
}
function manual($tpl) {
global $R;
$this->_parse();
foreach( $this->form as $attr_name => $arr ) {
if ( $arr['hidden'] ) {
$t = '<input type="hidden" name="'.$attr_name.'" value="'.$this->obj->get($attr_name).'">';
$tpl = $R->parse('hidden_items', $t, $tpl );
} else {
$tpl = $R->set( $attr_name .'_title', $arr['title'].($arr['mand']?'<span class="error">*</span>':''), $tpl );
$tpl = $R->set( $attr_name .'_html', $arr['html'], $tpl );
$tpl = $R->set( $attr_name .'_error', '<div class="error">'.$this->obj->errors[$attr_name].'</div>', $tpl );
}
}
return $tpl;
}
/**
* Автоматический блок формы
* @param string $tpl строка старого шаблонизатора
* @return html|object возвращает или строку старого шаблонизатора или объект для blade
*/
function autotpl($tpl = "") {
global $R;
$this->_parse();
$tplr = $R->getTpl( $this->templ, 'row' );
$tplr_chbox = $R->getTpl( $this->templ, 'row_checkbox' );
$tplm = $R->getTpl( $this->templ, 'mand' );
$tpls = [];
foreach( $this->form as $k => $v ) {
if ( in_array( $k, $this->obj->force_hidden ) ) continue;
if ( $v['hidden'] || ( in_array($k, $this->hidden_vars)) ) {
$tt = '<input type="hidden" name="' . $k . '" value="' . $this->obj->get( $k ) . '">';
$tpls[$k] = $tt;
} else {
$tt = $tplr;
if ($this->obj->attrs[$k]['type'] == 'checkbox' ) {
$tt = $tplr_chbox;
}
$tt = $R->set( 'attr_title', $v['title'], $tt );
$tt = $R->set( 'attr_html', $v['html'], $tt );
$tt = $R->set( 'attr_name', $k, $tt );
if ( $v['mand'] ) {
$tt = $R->set( 'attr_mand', $tplm, $tt );
} else {
$tt = $R->set( 'attr_mand', '' ,$tt );
}
if ( $v['error'] ) {
$tt = $R->set( 'attr_error', '<div>'.$v['error'].'</div>', $tt );
} else {
$tt = $R->set( 'attr_error', '', $tt );
}
$tpls[$k] = $tt;
}
}
// Старый шаблонизатор
if ($tpl != "") {
foreach( $tpls as $k => $v ) {
$tpl = $R->set($k . '_block', $v, $tpl);
}
$tpl = $this->manual($tpl);
return $tpl;
} else {
// Возвращаем в виде объекта
$retObj = new stdClass();
$tpls['id'] = '<input type="hidden" name="id" value="'.intval($this->obj->id).'">';
foreach( $tpls as $k => $v ) {
$retObj->$k = $v;
$htmlKey = $k . '_html';
if ( in_array( $k, $this->obj->force_hidden ) ) {
$retObj->$htmlKey = '';
} else {
if ($this->form[$k]['hidden'] || ( in_array($k, $this->hidden_vars)) ) {
$retObj->$htmlKey = '<input type="hidden" name="' . $k . '" value="' . $this->obj->get( $k ) . '">';
} else {
$retObj->$htmlKey = $this->form[$k]['html'];
}
}
}
return $retObj;
}
}
}
?>

View File

@ -0,0 +1,179 @@
<?php
class imageTransform {
var $filename;
var $ct;
var $src;
var $dst;
var $w;
var $h;
var $type = 'jpeg';
var $ct_to_type = array(
'image/jpeg' => 'jpeg',
'image/gif' => 'gif',
'image/png' => 'png'
);
var $output_format = 'jpeg';
function __construct($filename, $ct = "" ) {
$this->filename = $filename;
if (!$ct) $ct = mime_content_type($this->filename);
if (!$ct ) $ct = 'image/jpeg';
$this->ct = $ct;
$this->type = $this->ct_to_type[$ct];
$this->loadImage();
}
function loadImage() {
$this->src = $this->imagecreatefrom($this->filename);
$this->w = imageSX($this->src);
$this->h = imageSY($this->src);
}
function imagecreatefrom($filename) {
$fname = 'imagecreatefrom'.$this->type;
return $fname($filename);
}
function resize($w = 0, $h = 0, $zoomout = true) {
if (!$w ) {
$k = $this->h/$h;
$w = $this->w/$k;
}
if (!$h ) {
$k = $this->w/$w;
$h = $this->h/$k;
}
if (!$this->dst ) {
$this->create($w, $h);
}
$src_k = $this->w/$this->h;
$dst_k = $w/$h;
if ($src_k == $dst_k ) {
// Åñëè ïðîïîðöèÿ ñîâïàäàåò, òî ïðîñòî çóì
$this->zoom($w, $h);
}
// Èçìåíÿåì ñîîòíîøåíèå ñòîðîí, ïðèâîäèì src ê dst
if ( $src_k < 1 ) { // Åñëè source âåðòèêàëüíûé
if ( $dst_k > 1 ) {
if ($zoomout) { // èç | â _
$this->resize_w2h($w,$h);
} else {
$this->resize_w2w($w,$h);
}
} else {
if ($zoomout ) {
$this->resize_w2w($w,$h); // èç _ â |
} else {
$this->resize_w2h($w,$h);
}
}
} else {
if ( $dst_k > 1 ) {
if ($zoomout ) {
$this->resize_w2w($w,$h); // èç _ â |
} else {
$this->resize_w2h($w,$h);
}
} else {
if ($zoomout) { // èç | â _
$this->resize_w2h($w,$h);
} else {
$this->resize_w2w($w,$h);
} }
}
}
function resize_w2h($w, $h) {
$k = $this->w / $w;
$new_h = $this->h/$k;
$margin_top = ($h-$new_h)/2;
imagecopyresampled($this->dst,$this->src,0,$margin_top,0,0,$w,$new_h,$this->w,$this->h);
}
function resize_w2w($w, $h) {
$k = $this->h / $h;
$new_w = ($this->w/$k);
$margin_left = ($w - $new_w)/2;
imagecopyresampled($this->dst, $this->src, $margin_left, 0, 0, 0, $new_w, $h, $this->w, $this->h);
}
function zoom($w, $h) {
imagecopyresampled($this->dst,$this->src,0,0,0,0,$w,$h,$this->w,$this->h);
}
function custom($x, $y, $w, $h ) {
}
function create($w = 0, $h = 0) {
if (!$w) $w = $this->w;
if (!$h) $h = $this->h;
$this->dst = ImageCreateTrueColor($w, $h);
if (in_array($this->type, array('png','gif') ) ) {
imagesavealpha($this->dst, true);
$transparent = imagecolorallocatealpha($this->dst, 255, 255, 255, 127);
} else {
$transparent = imagecolorallocate($this->dst, 255, 255, 255);
}
imagefill($this->dst, 0, 0, $transparent);
}
function save($filename) {
$this->image($this->dst, $filename);
ImageDestroy($this->dst);
ImageDestroy($this->src);
}
function image($link, $filename = '') {
$fname = 'image'.$this->output_format;
if ($this->output_format == 'jpeg' ) {
$fname($link, $filename, 90);
} else {
$fname($link, $filename);
}
}
function addWM($logo, $center = false) {
if (!$this->dst) {
$this->create();
imagecopy($this->dst, $this->src, 0,0,0,0,$this->w,$this->h );
}
$logoImage = ImageCreateFromPNG($logo);
imageAlphaBlending($logoImage, false);
imageSaveAlpha($logoImage, true);
$trcolor = ImageColorAllocate($logoImage, 255, 255, 255);
ImageColorTransparent($logoImage , $trcolor);
if ($center ) {
$x = imageSX($this->dst)/2- imageSX($logoImage)/2;
$y = imageSY($this->dst)/2 - imageSY($logoImage)/2;
} else {
$x = rand(0, imageSX($this->dst)- imageSX($logoImage) );
$y = imageSY($this->dst) - ( imageSY($logoImage) * 1.2 );
}
imagecopy($this->dst, $logoImage, $x, $y, 0, 0, imageSX($logoImage), imageSY($logoImage));
ImageDestroy($logoImage);
}
function flush() {
Header('Content-Type: ' . array_search($this->output_format, $this->ct_to_type) );
$this->image($this->dst);
die();
}
}
?>

View File

@ -0,0 +1,138 @@
<?
class send_mail {
var $notify_type;
var $channel = 'email';
function send ($email, $title, $body, $mailfrom = '', $attaches=array() ) {
if (!$email ) return false;
if (!$mailfrom) $mailfrom = 'zakaz@zootovar-spb.ru';
if ( !$title ) {
$title = "Mail from " . _MAIL_FROM_;
}
$email = str_replace('@.','@', $email); // Часто пишут @.mail.ru
// Временно
//return $this->sendSMTP($email, $title, $body);
$title = '=?utf-8?B?'.base64_encode($title).'?=';
if ( $attaches ) {
$boundary = md5(uniqid(time()));
$headers =
"MIME-Version: 1.0;\r\n" .
"Reply-to: ".htmlspecialchars_decode($mailfrom)."\r\n".
"From: ".htmlspecialchars_decode($mailfrom)."\r\n".
"Content-type: multipart/related; type=\"text/html\"; charset=utf-8; boundary=\"".$boundary."\"";
$parts = "--$boundary\r\n";
$parts .= "Content-Type: text/html; charset=utf-8\r\n";
$parts .= "Content-Transfer-Encoding: base64\r\n";
$parts .= "\r\n"; // раздел между заголовками и телом html-части
$parts .= chunk_split(base64_encode($body));
foreach( $attaches as $arr ) {
$data = $arr['data'];
$name = $arr['name'];
$ct = $arr['ct'];
$disp = $arr['attach']?'attachment':'inline';
$parts .= "\r\n--$boundary\r\n";
$parts .= "Content-Type: ".$ct."; name=\"$name\"\r\n";
$parts .= "Content-Transfer-Encoding: base64\r\n";
$parts .= "Content-ID: <$name>\r\n";
$parts .= "Content-Disposition: inline; filename=\"$name\"\r\n";
$parts .= "\r\n"; // раздел между заголовками и телом прикрепленного файла
$parts .= chunk_split(base64_encode($data));
}
//$parts .= "\r\n--$boundary\r\n";
} else {
$headers =
"Reply-to: ".htmlspecialchars_decode($mailfrom)."\n".
"From: ".htmlspecialchars_decode($mailfrom)."\n".
"Content-Transfer-Encoding: base64\r\n".
"Content-type: text/html; charset=utf-8";
$parts = chunk_split(base64_encode($body));
}
return mail($email, $title, $parts, $headers);
}
function sendSMTP($email, $title, $body) {
require_once('smtp.class.php');
$mail = new KM_Mailer("smtp.yandex.ru", "587", "zakaz@zootovar-spb.ru", "xcHkoYJx", "tls");
if($mail->isLogin) {
if( $mail->send("zakaz@zootovar-spb.ru", $email, $title, $body) ) {
return true;
}
return false;
}
return false;
}
function to_pool($email, $title, $msg, $api_id = 1, $attach_ids = '', $from = '') {
if (!$email) return;
$email = trim($email);
/*
if ( !preg_match("/^([a-z0-9_\.-]+)@([a-z0-9_\.-]+)\.([a-z\.]{2,6})$/i",$email ) ) {
return;
}
*/
// Не отправляем на локальные адреса
if ( preg_match("/client\d{1,}@zootovar-spb.ru/", $email) ) {
return false;
}
// проверяем тип оповещения в стоп-листе клиента
if($this->notify_type){
$types_obj = new cobject('shop_notify_types');
$types_obj->byAttr('notify_type', $this->notify_type);
$user_obj = new cobject('shop_users');
$user_obj->byAttr('email', $email);
$stop_obj = new cobject('shop_notify_stoplist');
$db = $stop_obj->getDB()->q($stop_obj->getSelect(' AND `client_id`="'.$user_obj->id.'" AND `type_id`="'.$types_obj->id.'" AND `channel`="'.$this->channel.'"'));
if($db->nr()){
return false;
}
}
$obj = new cobject('_sys_mail_pool');
$obj->getDB()->q('INSERT INTO `_sys_mail_pool` (`id`,`email`,`title`,`msg`,`create_time`,`send_time`,`from`,`attach_ids`) VALUES (NULL,"'.db_escape_string($email).'","'.mysql_real_escape_string($title).'","'.mysql_real_escape_string($msg).'",'.time().', 0, "'.mysql_real_escape_string($from).'", "'.$attach_ids.'" )');
// Вместо пула - сразу шлём письмо
/*
$from = _MAIL_FROM_;
$this->send($email, $title, $msg, $from);
*/
}
function chunk_split_unicode($str, $l = 76, $e = "\r\n") {
$tmp = array_chunk(
preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY), $l);
$str = "";
foreach ($tmp as $t) {
$str .= join("", $t) . $e;
}
return $str;
}
}
?>

View File

@ -0,0 +1,664 @@
<?php
class cobject {
var $obj_name;
var $attrs = array();
var $attrs_vals = array();
var $id = 0;
var $errors = array();
var $global_type = 0; // 0 - локальный, 1 - глобальный
var $recursion_depth = 0;
var $force_hidden = array();
var $sql_where; // Глобальное ограничение на объект
var $save_sql = '';
var $diffed = array();
var $exceptPrimaryKeys = ['_sys_cat' => 'cat_id', // объекты где основной ключ не ID при сохранении
'_sys_cat_admin' => 'cat_id'];
/**
* Конструктор
* @param string $obj_name имя таблицы в DB
* @param integer $depth текущия глубина рекурсии (для предотвращения бесконечной рекурсии)
*/
function __construct( $obj_name, $depth = 0 ) {
global $statistica;
$statistica['objects_add']++;
$this->recursion_depth = ($depth+1);
$this->obj_name = $obj_name;
// Определяем тип объекта по имени
//if ( strpos($obj_name, '_sys_') !== false ) {
// All objects is local in basic mode
$this->global_type = 1;
//}
if ($depth <= 2 ) { // Не более 3х вложений!!
$this->getAttrs();
}
$this->attrs_vals = array();
}
/**
* Получить экземпляр базы данных, связанный с объектом
* @return [type] [description]
*/
function getDB() {
global $db, $core_db;
if ( $this->global_type == 1 ) {
return $core_db;
} else {
return $db;
}
}
/**
* Pагружаем атрибуты в объект
* @return [type] [description]
*/
private function getAttrs() {
global $objects_cache;
$curdb = $this->getDB();
if ( $objects_cache[$this->obj_name] ) {
foreach( $objects_cache[$this->obj_name] as $name => $arr ) {
$this->attrs[$name]['name'] = $name;
$this->attrs[$name]['type'] = $arr['attr_type'];
$this->attrs[$name]['templ'] = str_replace('[', '{', str_replace(']', '}', $arr['attr_templ']));
$this->attrs[$name]['desc'] = $arr['attr_desc'];
$this->attrs[$name]['hide'] = $arr['attr_hide'];
$this->attrs[$name]['mand'] = $arr['attr_mand'];
$this->attrs[$name]['attr_obj'] = $this->getAttrObj( $name, $arr['attr_type'] );
}
} else {
$db2 = $curdb->q("SELECT * FROM `_sys_datatypes` WHERE `obj_name` = '".$this->obj_name."' AND !`_sys_deleted` ORDER BY `attr_order` ASC");
while( $db2->r() ) {
$name=$db2->f('attr_name');
$objects_cache[$this->obj_name][$name] = $db2->lastRow;
$this->attrs[$name]['name'] = $name;
$this->attrs[$name]['type'] = $db2->f('attr_type');
$this->attrs[$name]['templ'] = str_replace('[', '{', str_replace(']', '}', $db2->f('attr_templ')));
$this->attrs[$name]['desc'] = $db2->f('attr_desc');
$this->attrs[$name]['hide'] = $db2->f('attr_hide');
$this->attrs[$name]['mand'] = $db2->f('attr_mand');
$this->attrs[$name]['attr_obj'] = $this->getAttrObj( $name, $db2->f('attr_type') );
}
}
}
/**
* Получить объект атрибута
* @param string $attr_name имя атрибута
* @param string $attr_type тип атрибута
* @return object
*/
function getAttrObj( $attr_name, $attr_type ) {
@list($type, $obj_link) = explode( '|', $attr_type );
$classname = 'attr_' . $type;
if ( class_exists( $classname ) ) {
$attr_obj = new $classname( $attr_name, $this);
return $attr_obj;
} else {
die( 'Заявленный класс "' . $classname . '" - не определен' );
}
}
/**
* Расширенный конструктор SQL запросов
* @param string $sql_from что берём
* @param string $sql_where с каким where ограничением
* @param integer $show_deleted забираем ли удалённые объекты (по умолчанию нет)
* @return string SQL запрос
*/
function getSelectEx( $sql_from ="*", $sql_where = "", $show_deleted = 0) {
$sql = "SELECT " . $sql_from;
$sql .= " FROM `" . $this->obj_name . "` WHERE 1 ";
if (!$show_deleted && isset($this->attrs['_sys_deleted']) ) {
$sql .= " AND !`".$this->obj_name."`.`_sys_deleted` ";
}
$sql .= $sql_where;
return $sql;
}
/**
* Конструктор SQL запросов
* @param string $sql_where_in where ограничение
* @param integer $show_deleted забираем ли удалённые объекты (по умолчанию нет)
* @return string SQL запрос
*/
function getSelect($sql_where_in = "", $show_deleted = 0) {
global $auth, $cat;
$sql_joins = '';
/* Access deleted */
$sql_where = '';
if (!$show_deleted && isset($this->attrs['_sys_deleted']) ) {
$sql_where .= " AND !`".$this->obj_name."`.`_sys_deleted` ";
}
/* Access Group */
if ( isset($this->attrs['access_group']) && ( $auth->user_id != _ROOT_USER_ID ) ) {
if ( !$auth->is_login() ) {
$sql_where .= " AND !`".$this->obj_name."`.`access_group` ";
} else {
$tmp_sql[] = ' !`'.$this->obj_name.'`.`access_group` ';
foreach( $auth->groups as $v ) {
$tmp_sql[] = ' FIND_IN_SET('.$v.',`'.$this->obj_name.'`.`access_group`) ';
}
if ($tmp_sql ) {
$sql_where .= " AND (" . implode(" OR ", $tmp_sql ) . " ) ";
} else {
$sql_where .= " AND !`".$this->obj_name."`.`access_group` ";
}
}
}
/* access geo */
if ( isset($this->attrs['access_city']) && !defined('_ADMINKA_') ) {
global $geoip;
$sql_where .= " AND ( FIND_IN_SET(".$geoip->city_id.", `".$this->obj_name."`.`access_city` ) OR `".$this->obj_name."`.`access_city` = '' ) ";
}
/* Global where */
if ( $this->sql_where ) {
$sql_where = $this->sql_where .' '. $sql_where;
}
/* incoming arg */
$sql_where .= $sql_where_in;
/* SELECT */
$sql = "SELECT ";
$sqls[] = " `".$this->obj_name."`.`id` ";
foreach( $this->attrs as $k => $arr ) {
$sqls[] = " `".$this->obj_name."`.`".$k."` ";
}
$sql .= implode(",", $sqls);
$sql .= " FROM `" . $this->obj_name . "` " . $sql_joins . " WHERE 1 ";
$sql .= $sql_where;
return $sql;
}
/**
* Загружаем данные в объект по ID
* @param integer $id ID из таблицы
* @param boolean $usecache Использовать ли кэш
*/
function byId( $id, $usecache = true ) {
global $cached_objects;
$this->diffed = array();
$this->save_sql = '';
if ($cached_objects[$this->obj_name][$id] && $usecache) {
$this->attrs_vals = $cached_objects[$this->obj_name][$id];
$this->id = $id;
} else {
$curdb = $this->getDB();
$db2 = $curdb->q( $this->getSelect( ' AND `'. $this->obj_name.'`.`id` = "'.$id.'" ', 1 ) );
$this->attrs_vals = array();
$this->id = 0;
if ( $db2->r() ) {
foreach( $this->attrs as $k => $arr ) {
$this->attrs_vals[$k] = $db2->f( $k );
}
$this->id = $id;
$cached_objects[$this->obj_name][$id] = $this->attrs_vals;
} else {
return false;
}
}
}
/**
* Сохраняет объект
* @param boolean $do_log логировать ли сохранение
* @param boolean $delayed отложенный UPDATE/INSERT
*/
function save($do_log = true, $delayed = false ) {
$curdb = $this->getDB();
/* только измененные атрибуты */
if ( empty( $this->diffed ) ) return false;
$this->diffed = array_unique($this->diffed);
foreach( $this->diffed as $key ) {
if ( $this->attrs[$key] ) {
$this->attrs[$key]['attr_obj']->presave();
}
}
foreach( $this->diffed as $key ) {
$val = $this->attrs_vals[$key];
if (is_array($val)) {
$val = trim_array($val);
$val = implode(',', $val);
}
$val = db_escape_string( $val );
$update[] = ' `'.$this->obj_name.'`.`'.$key.'` = "' . $val . '" ' ;
$insert[$key] = $val;
}
// Расширенный лог для товаров
$this->itemObjLog();
if ( $this->id ) {
if ($do_log) {
if ($this->global_type == 1 ) {
$db2 = $curdb->q('SELECT * FROM `'.$this->obj_name.'` WHERE `id` = ' . intval( $this->id ) );
if ( $db2->nr() ) {
$old_d = $db2->lastRow;
$new_d = $this->attrs_vals;
foreach( $old_d as $k=>$v ) {
if ( $k == 'id' ) continue;
if ( $k == 'full' ) continue;
if ( $new_d[$k] != $v ) {
$s_old[$k] = $v;
$s_new[$k] = $new_d[$k];
}
}
if ( $s_old || $s_new ) {
global $auth;
$db2->q("INSERT INTO `_sys_obj_log` (`datetime`,`user_id`,`obj_name`,`obj_id`,`old_data`,`user_ip`,`new_data`)
VALUES ('".time()."','".$auth->user_id."','".$this->obj_name."','".$this->id."','".db_escape_string(serialize($s_old))."','".$_SERVER['REMOTE_ADDR']."','".mysql_real_escape_string(serialize($s_new))."') ");
}
}
}
}
if ( $delayed ) {
$sql = 'UPDATE LOW_PRIORITY `'.$this->obj_name.'` SET ';
} else {
$sql = 'UPDATE `'.$this->obj_name.'` SET ';
}
$sql .= implode( ',', $update );
if (isset($this->exceptPrimaryKeys[$this->obj_name]) ) {
$saveKey = $this->exceptPrimaryKeys[$this->obj_name];
$sql .= ' WHERE `'.$this->obj_name.'`.`'.$saveKey.'` = "' . $this->get($saveKey) . '"';
} else {
$sql .= ' WHERE `'.$this->obj_name.'`.`id` = "' . $this->id . '"';
}
$curdb->q( $sql );
$this->save_sql = $sql;
global $cached_objects;
unset($cached_objects[$this->obj_name][$this->id]);
} else {
$sql = 'INSERT INTO `' . $this->obj_name . '` (`' . implode( '`, `', array_keys( $insert ) ) . '`) VALUES ( "' . implode( '", "', array_values( $insert ) ) . '")' ;
$db2 = $curdb->q( $sql );
$this->id = $db2->insert_id();
$this->save_sql = $sql;
if ($do_log) {
if ($this->global_type == 1 ) {
global $auth;
$db2->q("INSERT INTO `_sys_obj_log` (`datetime`,`user_id`,`obj_name`,`obj_id`,`old_data`,`user_ip`,`new_data`)
VALUES ('".time()."','".$auth->user_id."','".$this->obj_name."','".$this->id."','','".$_SERVER['REMOTE_ADDR']."','') ");
}
}
}
foreach( $this->diffed as $key ) {
if ( $this->attrs[$key] ) {
$this->attrs[$key]['attr_obj']->postsave();
}
}
}
/**
* Сбрасывает (обнуляет) объект
*/
public function reset() {
$this->byId(0);
$this->save_sql = '';
$this->diffed = [];
}
/**
* Создает новые объект с данными текущего, но без ID
*/
function copy() {
$this->id = 0;
$this->save_sql = '';
foreach($this->attrs_vals as $k => $v) {
$this->diffed[] = $k;
}
}
/**
* Сохраняет объект как копию
* @param boolean $do_log логировать ли запрос
*/
function saveAsCopy($do_log = true) {
$this->id = 0;
$this->save_sql = '';
foreach( $this->attrs as $key => $val ) {
$this->diffed[] = $key;
}
return $this->save($do_log);
}
/**
* Удаляет объект
*/
function del() {
$curdb = $this->getDB();
if ( $this->id ) {
if ( isset($this->attrs['_sys_deleted']) ) {
$curdb->q('UPDATE `'.$this->obj_name.'` SET `'.$this->obj_name.'`.`_sys_deleted` = "1" WHERE `'.$this->obj_name.'`.`id` = "'.$this->id.'"');
} else {
$curdb->q('DELETE FROM `'.$this->obj_name.'` WHERE `'.$this->obj_name.'`.`id` = "'.$this->id.'"');
}
}
global $cached_objects;
unset($cached_objects[$this->obj_name][$this->id]);
}
/**
* Заплоняет объект строчкой из базы данных
* @param db $db ссылка на подключение к базе данных
*/
function lRow( $db ) {
$this->diffed = array();
foreach( $this->attrs as $key => $val ) {
$this->attrs_vals[$key] = $db->f( $key );
}
$this->id = $db->f('id');
global $cached_objects;
$cached_objects[$this->obj_name][$db->f('id')] = $this->attrs_vals;
return $this;
}
/**
* Заполняет объект из POST данных формы
*/
function lPost() {
if ( intval( $_POST['id']) ) {
$this->byId( intval( $_POST['id']) );
}
foreach( $this->attrs as $k => $val ) {
if (in_array($k, $this->force_hidden ) ) continue;
if ( !isset($_FILES[$k]) && !isset($_POST[$k]) && (!$this->attrs[$k]['mand']) ) {
if ( substr( $val['name'], -8 ) != '_preview' ) {
$this->set($k,'');
}
} else {
$val['attr_obj']->lPost();
}
// $this->diffed[] = $k;
}
$this->id = intval($_POST['id']);
}
/**
* Меняет данных атрибута (сеттер)
* @param string $attr_name имя атрибута
* @param string $value данные
*/
function set( $attr_name, $value ) {
// Проверка на совпадение, с учётом приведения типов
// в this->attrs_vals всегда лежат string
if ( (string)$this->attrs_vals[$attr_name] === (string)$value ) return false;
if ( $this->attrs_vals[$attr_name] === '0' && $value === "") return false;
if ( $this->attrs_vals[$attr_name] === '0' && $value === false ) return false;
if ( $this->attrs_vals[$attr_name] === '1' && $value === true ) return false;
if ( is_numeric($this->attrs_vals[$attr_name]) && is_numeric($value) && $this->attrs_vals[$attr_name] == $value ) return false;
$this->attrs_vals[$attr_name] = $value;
if (!in_array($attr_name, $this->diffed)) {
$this->diffed[] = $attr_name;
}
return true;
}
/**
* Получает данные атрибута из объекта
* @param string $attr_name имя атрибута
* @return string
*/
function get( $attr_name ) {
return $this->attrs_vals[$attr_name];
}
/**
* Отрисовка атрибутов через шаблонизатор Render
* @param string $tpl переменная-шаблон
* @param boolean $crop укороченный вывод
* @param array $params устарело - не используется
* @return [type] [description]
*/
function assign( $tpl, $crop = false, $params = array() ) {
global $R;
$vars = $R->getVars($tpl);
foreach( $this->attrs as $key => $val ) {
if ( in_array( $key, $vars ) ) {
if ($this->recursion_depth < 3 ) {
$tpl = $R->set( $key, $this->attrs[$key]['attr_obj']->render_text($crop), $tpl );
} else {
$tpl = $R->set( $key, $this->get($key), $tpl );
}
}
$tpl = $R->set( $key.'_real', $this->get($key), $tpl );
$tpl = $R->set( $key.'_money', number_format((float)$this->get($key), 2), $tpl );
}
$tpl = $R->set( "id", $this->id, $tpl );
$tpl = $R->set( $this->obj_name."_id", $this->id, $tpl );
return $tpl;
}
function validate() {
$valid = true;
foreach( $this->attrs as $attr_name=>$attr ) {
if (in_array($attr_name, $this->force_hidden ) ) continue;
if ($attr['mand'] && !$this->attrs_vals[$attr_name]) {
$this->errors[$attr_name] = 'Поле не заполнено';
$valid = false;
} elseif ( $this->attrs_vals[$attr_name] ) {
$err = $attr['attr_obj']->validate();
if ( $err && $err !== true ) {
$this->errors[$attr_name] = $err;
$valid = false;
}
}
}
return $valid;
}
function set_hidden( $attr_name ) {
$this->force_hidden[] = $attr_name;
}
function set_no_hidden( $attr_arr = array() ) {
foreach( $this->attrs as $k => $v ) {
if (!in_array($k, $attr_arr ) ) {
$this->force_hidden[] = $k;
}
}
}
function setSqlWhere( $attr_name, $sql_where ) {
if ( $this->attrs[$attr_name] ) {
$this->attrs[$attr_name]['attr_obj']->setSqlWhere($sql_where);
}
}
function addSqlWhere( $attr_name, $sql_where ) {
if ( $this->attrs[$attr_name] ) {
$this->attrs[$attr_name]['attr_obj']->setSqlWhere( $this->attrs[$attr_name]['attr_obj']->sql_where . $sql_where);
}
}
function setError($attr_name, $error) {
$this->errors[$attr_name] = $error;
}
function getSize( $sql_where = '' ) {
$db2 = $this->getDB()->q( $this->getSelectEx(' count(*) as `c` ', $sql_where ) );
$db2->nr();
return intval( $db2->f('c') );
}
function getList( $sql_where = '', $value = 'title' ) {
$db2 = $this->getDB()->q( $this->getSelect( $sql_where ) );
$lst = array();
while($db2->nr()) {
$lst[$db2->f('id')] = $db2->f($value);
}
return $lst;
}
function itemObjLog() {
global $auth;
// array('shop_item', 'shop_item_variants','shop_item_chars','shop_item_images')
if (!in_array($this->obj_name, array('shop_item', 'shop_item_variants',/*'shop_item_chars',*/'shop_item_images') ) ) return;
$skipFields = array('nostock_tmp', 'stock_data', 'stock_roz', 'in_stock', 'stock_im', 'in_stock_im');
$data = array();
$data['datetime'] = time();
$data['ip'] = $_SERVER['REMOTE_ADDR'];
$data['user_id'] = $auth->user_id;
$data['obj_name'] = $this->obj_name;
$data['script_name'] = $_SERVER['PWD'].'/'.$_SERVER['PHP_SELF'];
switch( $this->obj_name ) {
case 'shop_item':
$data['item_id'] = $this->id;
$data['variant_id'] = 0;
break;
case 'shop_item_variants':
$data['item_id'] = $this->get('item_id');
$data['variant_id'] = $this->id;
break;
default:
$data['item_id'] = $this->get('item_id');
$data['variant_id'] = $this->id;
break;
}
$old = array();
if ($this->id ) {
/* OldVals */
$curdb = $this->getDB();
$db2 = $curdb->q('SELECT * FROM `'.$this->obj_name.'` WHERE `id` = ' . intval( $this->id ) );
if ( $db2->nr() ) {
$old = $db2->lastRow;
}
}
foreach( $this->diffed as $field ) {
if (in_array( $field, $skipFields ) ) continue;
$newval = $this->attrs_vals[$field];
$oldval = $old[$field];
if ($newval == $oldval ) continue;
$data['field_name'] = $this->attrs[$field]['name'];
if (!$newval) {
$data['change_type'] = 3;
} elseif( !$oldval ) {
$data['change_type'] = 1;
} else {
$data['change_type'] = 2;
}
$data['old_value'] = db_escape_string($oldval);
$data['new_value'] = db_escape_string($newval);
$sql = 'INSERT DELAYED INTO `shop_item_change_log` (`'.implode("`, `",array_keys($data)).'`) VALUES ("'.implode('", "', $data).'") ';
$curdb = $this->getDB();
$db2 = $curdb->q( $sql );
}
}
function getCollection($sql_where = "", $show_deleted = 0) {
return new cobject_collection($this, $sql_where, $show_deleted);
}
}
/**
* Класс для коллекции объектов.
* Так удобнее работать с blade шаблонами
*/
class cobject_collection {
var $obj;
var $db;
// Готовим запрос в базу
function __construct($obj, $sql_where, $show_deleted = 0) {
$this->obj = $obj;
$this->db = $this->obj->getDB()->q($this->obj->getSelect($sql_where));
}
// Следующий экземпляр коллекции
public function next() {
if ($this->db->nr()) {
$this->obj->lRow($this->db);
return true;
} else {
return false;
}
}
// Получение свойства
public function __get($key) {
return $this->render($key);
}
// Получение реального значения свойства
public function get($key) {
return $this->obj->get($key);
}
// Отрисовка
public function render($key, $crop = false) {
if (isset($this->obj->attrs[$key])) {
if ($this->obj->recursion_depth < 3 ) {
return $this->obj->attrs[$key]['attr_obj']->render_text($crop);
} else {
return $this->obj->get($key);
}
} else {
if ($key == 'id') return $this->obj->id;
return '';
}
}
}
?>

View File

@ -0,0 +1,98 @@
<?php
class render {
var $tpl_cache = array();
function globalsets($tpl) {
global $cat, $url_arr,$uauth, $shop, $geoip;
/* includes */
if ( preg_match_all('/{include:(.*?)}/', $tpl, $arr ) ) {
global $cat;
$path = _BASE_DIR . 'tpls/';
foreach( $arr[1] as $filename ) {
if ( !$this->tpl_cache[$path . $filename][''] ) {
$subtpl = @file_get_contents($path . $filename);
$this->tpl_cache[$path . $filename][''] = $subtpl;
} else {
$subtpl = $this->tpl_cache[$path . $filename][''];
}
$subtpl = @file_get_contents($path . $filename);
$tpl = $this->set('include:'.$filename, $subtpl, $tpl );
}
}
/* global sets */
$tpl = $this->set('cur_cat', $cat->cat, $tpl);
$tpl = $this->set('cur_year', date('Y'), $tpl);
$tpl = $this->set('cur_date', date('d.m.Y'), $tpl);
$tpl = $this->set('cur_cat_name', $cat->cat_name, $tpl);
$tpl = $this->set('getRand', rand(), $tpl);
$tpl = $this->set('_SITE_TITLE_', _SITE_TITLE_, $tpl);
$tpl = $this->set('_SITE_ROOT_', _SITE_ROOT_, $tpl);
$tpl = $this->set('_STATIC_ROOT_', _STATIC_ROOT_, $tpl);
if ($url_arr) {
$tpl = $this->set('cur_url', implode('/', $url_arr), $tpl);
}
/* */
return $tpl;
}
function getTpl($filename, $section ='', $path = '') {
if (!$path ) $path = _BASE_DIR . '/tpls/';
if ( !$tpl_cache[$path . $filename][$section] ) {
$tpl = file_get_contents($path . $filename);
if ( $section ) {
preg_match ("/\#\[".$section."\]\#(.*?)\#\[!".$section."\]\#/s", $tpl, $r);
$tpl = $r[1];
}
$tpl_cache[$path . $filename][$section] = $tpl;
} else {
$tpl = $tpl_cache[$path . $filename][$section];
}
$tpl = $this->globalsets($tpl);
return $tpl;
}
function set($x, $y, $tpl) {
global $statistica;
$starttime = microtime(true);
$tpl = str_replace('{' . $x . '}', $y, $tpl);
$statistica['render_time'] += microtime(true) - $starttime;
return $tpl;
}
function parse($x, $y, $tpl) {
global $statistica;
$starttime = microtime(true);
$tpl = str_replace('{' . $x . '}', $y . '{' . $x . '}', $tpl);
$statistica['render_time'] += microtime(true) - $starttime;
return $tpl;
}
function clear($tpl) {
global $statistica;
$starttime = microtime(true);
$tpl = preg_replace ("/\{[^\s]{1,}?\}/", '', $tpl);
$statistica['render_time'] += microtime(true) - $starttime;
return $tpl;
}
function getVars($tpl) {
preg_match_all ("/{(.*?)}/", $tpl, $r);
return $r[1];
}
}
?>

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