This commit is contained in:
indeferend
2021-05-23 06:26:34 +05:00
commit df825e3d2f
56 changed files with 24076 additions and 0 deletions

48
.unotes/unotes_meta.json Normal file
View File

@@ -0,0 +1,48 @@
{
"name": "",
"isOrdered": true,
"folders": {
"CLASSES": {
"name": "CLASSES",
"isOrdered": true,
"folders": {
"core": {
"name": "core",
"isOrdered": true,
"folders": {},
"files": {
"doc__LE_FS": 0
}
}
},
"files": {}
},
"LE": {
"name": "LE",
"isOrdered": true,
"folders": {},
"files": {
"core_fuctions": 0
}
},
"MODULES": {
"name": "MODULES",
"isOrdered": true,
"folders": {},
"files": {}
},
"PUB": {
"name": "PUB",
"isOrdered": true,
"folders": {},
"files": {}
},
"TPL": {
"name": "TPL",
"isOrdered": true,
"folders": {},
"files": {}
}
},
"files": {}
}

9
CLASSES/blog.php Normal file
View File

@@ -0,0 +1,9 @@
<?php
class blog_model
{
}

206
CLASSES/core/LE_FS.php Normal file
View File

@@ -0,0 +1,206 @@
<?php
/** @var \DB $db*/
if(!defined("I")) die;
//работа с файлами
class LE_FS
{
//+++добавить рекурсивное добавление родительских...
public static function create_folder ($path,$permissions=0755)
{
if(!is_dir($path)) mkdir($path, $permissions);
}
public static function clear_folder($path)
{
$path = rtrim($path,"/")."/";
if (!is_dir($path) || !($handle = opendir($path))) return;
while(false !== ($f = readdir($handle)))
{
if($f == "." || $f == "..") continue;
$obj=$path.$f;
if (is_file($obj))
unlink($obj);
elseif (is_dir($obj))
LE_FS::clear_folder($obj);
}
closedir($handle);
}
//рекурсивное копирование папки LE_FS::copy_folder($src, $dest);
public static function copy_folder($src, $dest) {
if (stripos($src,".DS_Store")>0) return false;
if ( is_dir( $src ) ) {
if (!file_exists($dest)) mkdir($dest, 0777, true);
$d = dir( $src );
while ( false !== ( $entry = $d->read() ) ) {
if ( $entry != '.' && $entry != '..' )
LE_FS::copy_folder( "$src/$entry", "$dest/$entry");
}
$d->close();
}
elseif (!file_exists($dest))
{
copy($src, $dest);
echo 'copy file <b>'.$src.'</b> to <b>'.$dest."</b>\n<br>";
}
}
public static function dir_files($dir,$func=false)
{
if (!$dir||empty($dir)||!is_dir($dir)) return 1;
if($func===false) return 2;
$d = dir( $dir );
while ( false !== ( $entry = $d->read() ) ) {
if ( $entry == '.' || $entry == '..' ) continue;
$func($entry);
}
$d->close();
}
//LE_FS::save_from_post($inp=['f_name'=>,'path'=>])
public static function SAVE_POST($inp,$debug=false)
{
$f_name = (isset($inp['f_name'])) ? $inp['f_name'] : 'file';
if (!isset($inp['path']) || !is_dir($inp['path'])) return false;
$inp['path'] = rtrim($inp['path']);
// echo $inp['path'];
if (!isset($_FILES[$f_name])) return false;
$F = $_FILES[$f_name];
// echo_arr($F);
$SAVE_FILE = function($path,$index=false) use (&$F,&$debug)
{
$f_inf=[];
if ($index!==false)
{
if (!isset($F["tmp_name"][$index])) return false;
$f_inf['tmp_name'] = $tmp_name = $F["tmp_name"][$index];
$f_inf['name'] = $file_name = $F["name"][$index];
$f_inf['type'] = $F["type"][$index];
$f_inf['size'] = $F["size"][$index];
}
else
{
if (!isset($F["tmp_name"])) return false;
$f_inf['tmp_name'] = $tmp_name = $F["tmp_name"];
$f_inf['name'] = $file_name = $F["name"];
$f_inf['type'] = $F["type"];
$f_inf['size'] = $F["size"];
}
// echo $tmp_name.BR;
// echo $file_name.BR;
if (!is_uploaded_file($tmp_name)) return false;
$n = LE_FS::GEN_FNAME($file_name, $path);
$out = $path.DS.$n;
if (!move_uploaded_file($tmp_name, $out)) return false;
if (!file_exists($out)) return false;
if($debug!==false) $debug[$n] = $f_inf;
return $n;
};
if (is_array($F['tmp_name']))
{
$cnt = count($F['tmp_name']);
$res = [];
for ($i=0;$i<$cnt;$i++)
{
$_fn = $SAVE_FILE($inp['path'],$i);
if ($_fn!==false) $res[] = $_fn;
}
}
else
{
return $SAVE_FILE($inp['path']);
}
$cnt = count($res);
if (!$cnt>0) return false;
if ($cnt===1) return $res[0];
return $res;
}
public static function GEN_FNAME($inp_name = false, $path = false, $prefix=false)
{
$ext = ($inp_name) ? '.'.pathinfo ($inp_name,PATHINFO_EXTENSION) : ''; //extension .jpg
//file name alphabet
$fn_alphabet = [0,1,2,3,4,5,6,7,8,9,'A','B','C','D',
'E','F','G','H','I','J','K','L','M','N','O','P','Q',
'R','S','T','U','V','W','X','Y','Z','_','-'
];
$microtime = microtime(1);
$create_time = 1540388275;
$diff_time = Ceil($microtime*10000)-($create_time*10000);
$new = int2alphabet($fn_alphabet,$diff_time);
if ($prefix!==false) $new = $prefix.$new;
//проверка существования
if ($path && is_dir($path))
{
$part = rtrim($path,DS);
$i=1;
while(is_file($path . DS . $new.$ext))
{
if ($i>100) exit("problem gen file name!!!");
$new.=$fn_alphabet[rand(0,27)];
$i++;
}
}
return $new.$ext;
}
public static function Apply2Files($path,&$func,$recouse=0)
{
$path = rtrim($path,"/\\").DS;
if (!is_dir($path) || !($handle = opendir($path))) return;
while(false !== ($f = readdir($handle)))
{
if($f == "." || $f == "..") continue;
$obj=$path.$f;
if (is_file($obj))
$func($obj);
elseif (is_dir($obj) && $recouse)
LE_FS::Apply2Files($obj,$func,$recouse);
}
closedir($handle);
}
}

View File

@@ -0,0 +1,145 @@
<?php
abstract class LE_MOD_CONTROLLER
{
public $aliases, $params_url, $model,$cont_type;
function __construct($params_url=false,&$model=false)
{
$this->params_url = $params_url;
$this->model = &$model;
}
//точка входа
public function start()
{
//ajax methods
if (isset($_POST['ajax'])) return $this->ajax();
if (LE::$QUERY_DATA_TYPE=='json') return $this->json();
list($mod,$params) = $this->router();
if (!empty($mod) && isset($this->aliases[$mod])) $mod = $this->aliases[$mod];
$mod = "_inp_".$mod;
if ($mod=="_inp_" || !method_exists($this,$mod)) return $this->_inp_default($params);
return $this->$mod($params);
}
protected function router()
{
//echo_arr($this->params_url);
$url = $this->params_url[3];
$url = PRE::DOWN($url);
preg_match('!([^:]*)[:]?(.*)!ui',$url,$out);
//echo_arr($out);
return [$out[1],$out[2]];
}
protected function ajax()
{
//out without template
if (property_exists(LE::$TPL,'clear')) LE::$TPL->clear=1;
$mod = trim(arr_v($_POST,'mod',''));
if (empty($mod)) return false;
$mod = "_ajx_".$mod;
$data=false;
if (isset($_POST['data']))
{
$data = $_POST['data'];
if (!is_array($data) && !empty($data)) $data = json_decode($data,1);
}
if (!method_exists($this,$mod)) return false;
$res = $this->$mod($data);
//возвращать массив ответа как есть, не оборачивая в data
if (isset($res['as_is']) && $res['as_is'])
{
unset($res['as_id']);
$out = $res;
}
elseif ($res===false)
{
$out = ['success'=>0]; //error
}
else
{
$out = ['success'=>1];
$out['data'] = $res;
}
return json_encode($out);
}
protected function _inp_default($inp)
{
return false;
}
protected function json()
{
$postData = file_get_contents('php://input');
$data = json_decode($postData,1);
if (property_exists(LE::$TPL,'clear')) LE::$TPL->clear=1;
$method = trim(arr_v($data,'method',''));
if (empty($method)) return false;
$method = "_ajx_".$method;
if (!method_exists($this,$method)) return false;
unset($data['method']);
$res = $this->$method($data);
//возвращать массив ответа как есть, не оборачивая в data
if (isset($res['as_is']) && $res['as_is'])
{
unset($res['as_id']);
$out = $res;
}
elseif ($res===false)
{
$out = ['success'=>0]; //error
}
else
{
$out = ['success'=>1];
$out['data'] = $res;
}
return json_encode($out);
}
//301 redirect
public function move2new($url)
{
header("HTTP/1.1 301 Moved Permanently");
header("Location: ".$url);
exit();
}
}

View File

@@ -0,0 +1,71 @@
<?php
class LE_MOD_LOAD {
public $m1=false,$m2=false,$space_list=[],$mod_aliases=[];
public $init_path=false,$mod_path=false,$url;
function __construct($autorun=1)
{
$this->m1=SYSDIR."MODULES".DS;
$this->m2=APPDIR."MODULES".DS;
$this->space_list = SYSCONF::$SPACE_LIST;
$this->mod_aliases = SYSCONF::$MOD_ALIASES;
if ($autorun) $this->parse_url();
}
public function parse_url()
{
$query = LE_REQUEST::url2arr()['query_clr'];
$spaces_str = implode('|',array_keys($this->space_list));
preg_match('!^/('.$spaces_str.')?/?([^/?]*)/?(.*?)$!simu', $query,$res);
$this->url = $res;
$space_in_q = $res[1];
$mod_in_q = $res[2];
$space=SYSCONF::$DEFAULT_MODSPACE; //default
if (!empty($space_in_q))
{
$space = $this->search_key($this->space_list,$space_in_q);
if ($space===false) return false;
}
if ($this->select_path($space)===false) return false;
$mod=arr_v(SYSCONF::$DEFAULT_MODULE,$space,false); //default
if (!empty($mod_in_q))
{
$mod_rr=false;
if (isset($this->mod_aliases[$space]))
$mod_rr = $this->search_key($this->mod_aliases[$space],$mod_in_q);
$mod = ($mod_rr) ? $mod_rr : $mod_in_q;
}
$this->init_path = $this->select_path($space,"__space_init.php");
$this->mod_path = $this->select_path($space,$mod.".php");
}
public function select_path($space,$path="")
{
$app_path = $this->m2.$space.DS.$path;
$sys_path = $this->m1.$space.DS.$path;
if (file_exists($app_path)) return $app_path;
if (file_exists($sys_path)) return $sys_path;
return false;
}
public function search_key($arr,$key)
{
foreach ($arr as $tpl => $val)
if(preg_match('!^('.$tpl.')$!simu', $key)) return $val;
return false;
}
}

278
CLASSES/core/LE_MYSQL.php Normal file
View File

@@ -0,0 +1,278 @@
<?php
class LE_MYSQL
{
public $l,$cnt = 0,$debug=0,$echo_sql=0;
private $cnf = [];
function __construct(&$cnf)
{
$this->cnf = &$cnf;
if (defined("DEBUG") && DEBUG==1) $this->debug=1;
$this->connect($cnf);
}
//exit and echo error
protected function err($txt)
{
http_response_code(503);
exit($txt);
}
/*****************************
| private helpers functions |
*****************************/
protected function create_connect()
{
if (isset($this->cnf['socket']) && !empty($this->cnf['socket']))
return new mysqli(NULL, $this->cnf['user'], $this->cnf['pass'], $this->cnf['db_name'], NULL,
$this->cnf['socket']);
return new mysqli($this->cnf['host'], $this->cnf['user'], $this->cnf['pass'], $this->cnf['db_name']);
}
public function connect()
{
$this->l = $this->create_connect();
if ($this->l->connect_errno) $this->err("ERROR CONNECT DB");
$this->sess_conf();
}
private function sess_conf()
{
$this->query("set names utf8");
$this->query("SET @@session.time_zone = '+00:00'");
}
public function check_conn ($debug=0)
{
if ($this->l->ping()!==false) return;
//проверим еще раз не переподключился ли он автоматом
usleep(500);
if ($this->l->ping()===false) $this->connect();
}
/*****************************
| query & anwer functions |
*****************************/
public function query($s, $buffer = true, $o = [])
{
$this->cnt++; //счетчик запросов
$buf = ($buffer) ? MYSQLI_STORE_RESULT : MYSQLI_USE_RESULT;
$type = (isset($o['type'])) ? $o['type'] : $this->detect($s);
if ($this->echo_sql) echo $s.BR;
$res = $this->l->query($s, $buf);
$e = ($this->l->error);
if (!empty($e)) $this->err(($this->c['debug'] ? $e . ' <br>(' . $s . ')' : 'ERR QUERY!!!'));
unset($e, $buf);
return $this->answer($res, $type, $o);
}
private function detect($s) {
if ((stripos($s, 'select', 0) !== false)) return 'S';
if ((stripos($s, 'SHOW', 0) !== false)) return 'S';
if ((stripos($s, 'insert', 0) !== false)) return 'I';
if ((stripos($s, 'update', 0) !== false)) return 'U';
if ((stripos($s, 'delete', 0) !== false)) return 'D';
if ((stripos($s, 'truncate', 0) !== false)) return 'T';
}
private function answer(&$r, $t_, $o) {
$t = &$this;
$l = &$this->l;
switch ($t_) {
case 'S':
if ((isset($o['row']) && $o['row']) || (isset($o['val']) && $o['val']))
{
$r_ = $this->get_row($r);
$r->free_result();
if (isset($o['val']) && $o['val']) return $r_[trim($o['val'])];
return $r_;
}
return $r;
break;
case 'I':
return $l->insert_id;
break;
case 'U';
case 'T';
case 'D';
return $l->affected_rows;
break;
}
return false;
}
public function get_row(&$r)
{
return ($r) ? mysqli_fetch_assoc($r) : FALSE;
}
/*****************************
| query prepare functions |
*****************************/
public function prepare($s)
{
return $this->l->real_escape_string($s);
}
public function arr2in($ids,$str=false)
{
if ($str) array_map(function($id){return "'".$id."'";},$ids);
$ids = (is_array($ids)) ? implode(',',$ids) : $ids;
return $this->prepare($ids);
}
public function gen_set($arr)
{
$arr_ = [];
if (count($arr)) {
foreach ($arr as $k => &$v) {
$arr_[] = "`" . $k . "`='" . (($v === '###') ? '' : $this->prepare($v)) . "'";
}
}
if (!count($arr_) > 0) {
return false;
}
unset($arr);
return implode(', ', $arr_);
}
/**********************
| result functions |
**********************/
public function count(&$res)
{
if (!$res || gettype($res)!=="object") return false;
return mysqli_num_rows ($res);
}
public function cnt(&$res) {return $this->count($res);}
public function res2arr($res = 0,$key=false,$shift_reg=false)
{
$res_arr = [];
if($key===false)
while($r = $this->get_row($res)) $res_arr[] = $r;
else
while($r = $this->get_row($res))
{
$_key = ($shift_reg) ? PRE::SHIFT($r[$key],$shift_reg) : $r[$key];
$res_arr[$_key] = $r;
}
return $res_arr;
}
public function found_rows()
{
return $this->query("SELECT FOUND_ROWS() as `cnt`", false, ['val' => 'cnt']);
}
/****************
QUERY GENERATORS
****************/
public function INS($table, $val_arr)
{
$table = $this->prepare($table);
$set_str = $this->gen_set($val_arr);
$sql = 'INSERT INTO `' . $table . '` SET ' . $set_str;
return $this->query($sql,0,['type'=>'I']);
}
public function UPD($table, $val_arr, $id, $idf = 'id',$str_key=false)
{
if (empty($id)) $this->err("ERR DB UPD");
$table = $this->prepare($table);
$set_str = $this->gen_set($val_arr);
$id_field = $this->prepare($idf);
$in_list = $this->arr2in($id,$str_key);
$sql = 'UPDATE `' . $table . '` SET ' . $set_str . ' WHERE `' . $id_field . '` IN (' . $in_list . ')';
return $this->query($sql,0,['type'=>'U']);
}
public function DEL($table, $id, $idf = "id",$str=false)
{
if (is_array($id) && !count($id)) return false; //нечего удалять, если ничего не передали
if (!is_array($id)) $id = [$id];
$table = $this->prepare($table);
$id_field = $this->prepare($idf);
$in_list = $this->arr2in($id);
$sql = 'DELETE FROM `' . $table . '` WHERE `' . $id_field . '` IN(' . $in_list.')';
return $this->query($sql,0,['type'=>'D']);
}
//ins or upd return index
public function SAVE($t,$v,$idf="id")
{
if (!isset($v[$idf]) || $v[$idf]==0) return $this->INS($t,$v);
$id = $v[$idf]; unset($v[$idf]);
//upd
if ($id>0 && count($v)>0) $this->UPD($t,$v,$id,$idf);
//delete
if ($id<0) $this->DEL($t,($id*-1),$idf);
return $id;
}
/*****************
* custom queries *
*****************/
public function query_arr($sql,$key=false,$shift_reg=0)
{
$res = $this->query($sql,0,['type'=>'S']);
$rez = $this->res2arr($res,$key,$shift_reg);
$res->free();
return $rez;
}
public function query_keyval($sql,$k=false,$v=false)
{
$k = trim($this->prepare($k));
$v = trim($this->prepare($v));
$res = $this->query($sql,0,['type'=>'S']);
$res_arr = [];
while($r = $this->get_row($res)) $res_arr[$r[$k]] = $r[$v];
return $res_arr;
}
public function query_single($s) {
return $this->query($s, false, ['row' => true]);
}
public function query_val($s,$v)
{
return $this->query($s, false, ['val' => $v]);
}
}

114
CLASSES/core/LE_REQUEST.php Normal file
View File

@@ -0,0 +1,114 @@
<?php
class LE_REQUEST {
public static function url2arr($s=false, $use_forwarded_host = false)
{
if ($s===false) $s = $_SERVER;
$res = [];
$ssl = (isset($s['HTTPS']) && $s['HTTPS'] == 'on' );
$port = (isset($s['SERVER_PORT'])) ? $s['SERVER_PORT'] : '80';
//хак для ssl nginx->apache
/*
if ((!$ssl) && function_exists('apache_request_headers'))
{
$h = apache_request_headers();
if (is_array($h) && isset($h['Nginx-Https']) && $h['Nginx-Https']=='on')
{
$ssl=true; $port=443;
}
}
*/
$protocol = strtolower($s['SERVER_PROTOCOL']);
$scheme = substr( $protocol, 0, strpos( $protocol, '/' ) ) . ( ( $ssl ) ? 's' : '' );
$standart_port = ((!$ssl && $port=='80') || ($ssl && $port=='443'));
$host="locahost";
if ($use_forwarded_host && isset( $s['HTTP_X_FORWARDED_HOST'] ))
$host = $s['HTTP_X_FORWARDED_HOST'];
elseif (isset( $s['HTTP_HOST']))
$host = $s['HTTP_HOST'];
elseif (isset( $s['SERVER_NAME']))
$host = $s['SERVER_NAME'];
$host_full = ($standart_port) ? $host : ($host.":".$port);
$query= isset($s['REQUEST_URI']) ? $s['REQUEST_URI'] : '';
$query_clr = preg_replace('!\?.*?$!','',$query);
return compact('ssl','port','scheme','standart_port','host','host_full','query','query_clr','protocol');
}
public static function TYPE_DETECT()
{
if (!isset($_SERVER["CONTENT_TYPE"])) return false;
$type = trim(explode(';',$_SERVER["CONTENT_TYPE"])[0]);
$type = PRE::DOWN($type);
if ($type=='application/json') return 'json';
return false;
}
public static function get2str($cust_get=null)
{
$get= (is_null($cust_get)) ? $_GET : $cust_get;
if (!is_array($get) || !count($get)) return '';
$arr = [];
foreach ($get as $k => $v)
$arr[] = $k.'='.$v;
return '?'.implode('&',$arr);
}
public static function str2get($q="")
{
if(empty($q)) return false;
$q = explode('&',$q);
$out=[];
$c = count($query);
for ($i=0;$i<$c;$i++)
{
$r=explode('=',$q[$i]);
if(!isset($r[1])) $r[1]='';
$out[$r[0]]=$r[1];
}
return $out;
}
public static function MOVE($u)
{
http_response_code(301);
header("Location: ".$u);
exit();
}
public static function FIX_URLCASE($u)
{
$q = arr_v($u,'query','');
if(empty($q)) return false;
if (PRE::SHIFT($q,'DOWN')!=$q)
LE_URL::MOVE(PRE::SHIFT($u['full'],'DOWN'));
}
}

View File

@@ -0,0 +1,7 @@
<?php
class LE_SQLITE
{
}

493
CLASSES/core/LE_TPL.php Normal file
View File

@@ -0,0 +1,493 @@
<?php
class LE_TPL {
public $load_tpls=[]; //список загруженных шаблонов
public $meta,$cont_top,$cont_bottom,$mod_cont,$head_cont;
public $vars=[],$prefix,$tpl_arr,$debug=0,$clear=0;
function __construct()
{
$this->meta = ['title'=>'','keywords'=>'','description'=>''];
$this->prefix="main";
$this->mod_cont="";
$this->vars = ['tpl_arr'=>&$this->tpl_arr,'tpl'=>&$this];
}
public function fetch($t,&$vars=array(),$prefix=false,$cache_en=false)
{
//выгружаем переменные в функцию
if (is_array($this->vars)) extract($this->vars);
if (is_array($vars)) extract($vars);
//определяем путь до шаблона
$this->load_tpls[] = $__p = $this->path($t,$prefix);
//инклудим шаблон, буферизуем его выхлоп
ob_start();
include($__p);
return ob_get_clean();
}
public function path($tpl_path,$prefix=false)
{
if ($prefix===false) $prefix = $this->prefix;
$path = $prefix.DS.$tpl_path.".tpl";
$path_app = realpath((APPDIR."TPL".DS.$path));
$path_sys = realpath((SYSDIR."TPL".DS.$path));
//echo APPDIR.$path.BR;
//echo SYSDIR.$path.BR;
if (is_file($path_app)) return $path_app;
if (is_file($path_sys)) return $path_sys;
exit($path." - NOT FOUND TPL");
}
public function display($prefix=false,$main_tpl="main")
{
//global $config,$db;
$tpl = &$this;
if ($this->debug) echo_arr($this->load_tpls);
if (arr_v($_POST,'clear')=='yes') $this->clear=1;
if($prefix===false) $prefix = $this->prefix;
include SYSDIR."TPL".DS.$prefix.DS."static_list.php";
$this->static_dep_apply();
$this->add_need_static();
$path= $this->path($main_tpl,$prefix);
if ($this->clear)
{
echo $this->mod_cont;
return ($this->clear=0);
}
$tpl_arr = &$this->tpl_arr;
include($path);
}
//static elements
public $need_st_list=[],$static_list=[],$static_dep=[],$top_st=[],$bottom_st=[];
public function need_static($inp)
{
if (!is_array($inp)) $inp = [$inp];
$cnt = count($inp);
for($i=0;$i<$cnt;$i++)
{
$v = $inp[$i];
if (empty($v)) continue;
$this->need_st_list[$v]=1;
}
}
public function static_dep_apply($dep_list=false)
{
if ($dep_list===false) $dep_list=$this->static_dep;
if (!is_array($dep_list) || empty($dep_list)) return;
$need = &$this->need_st_list;
foreach ($dep_list as $m_name => $dep_items)
{
//для выключенных модулей не применяем зависимости
if ( !(isset($need[$m_name]) && $need[$m_name]==1) ) continue;
foreach ($dep_items as $k => $dep)
{
$need[$dep]=1;
}
}
}
public function add_need_static()
{
$need = $this->need_st_list;
$list = $this->static_list;
foreach ($this->static_list as $key => $item)
{
$pos = arr_v($item,'pos',false);
$type = arr_v($item,'type',"");
$link = arr_v($item,'link',"");
//echo $link.BR;
if ($pos===false) $pos = ($type=="js") ? "bottom" : "top";
$mod=arr_v($item,'mod','default');
if ( !((isset($need[$mod]) && $need[$mod]==1) || $mod=='default') ) continue;
switch ($type)
{
case 'js':
$cont = $this->js($link);
break;
case 'css':
$cont = $this->css($link);
break;
default:
continue 2;
break;
}
if ($pos=="top")
$this->top_st[]=$cont;
else
$this->bottom_st[]=$cont;
}
$_gl = "\n\t";
$this->head_cont.=implode($_gl,$this->top_st);
$this->cont_bottom.=implode($_gl,$this->bottom_st);
//echo_arr($this->top_st);
}
public function css($p,$min=0)
{
return '<link rel="stylesheet" type="text/css" href="'.$this->p2min($p,$min,'css').'?v='.VER.'" />';
}
public function js($p,$min=0)
{
return '<script src="'.$this->p2min($p,$min,'js').'?v='.VER.'"></script>';
}
public function p2min($path,$min,$ext)
{
if ($min)
{
$path = str_replace('.'.$ext,'.min.'.$ext,$path);
$path = str_replace('min.min','min',$path);
}
return $path;
}
}
/*
<?php
MP::DEF('TPLDIR1',SYSDIR.'TPL'.DS);
MP::DEF('TPLDIR2',APPDIR.'TPL'.DS);
MP::DEF('LST_TPL',0);
MP::DEF('DBG_MGS',0);
MP::DEF('ST_DEV');
MP::DEF('ST_GLUE');
class TPL
{
public $template='default.tpl',$prefix='default',$clear=0;
public $js2bottom=1;
public $tpl_arr=[],$vars=[],$txt,$declare_parts=[], $load_tpls = []; //зарегистрированные части css и js
public $glue_arr = ['css'=>[],'js'=>[]];
function __construct() {
$this->tpl_arr = ['text'=>'','_html_'=>'','head_objects'=>'','meta_title'=>'','meta_keywords'=>'','meta_description'=>''];
$this->txt = &$this->tpl_arr['text'];
$this->vars = ['tpl_arr'=>&$this->tpl_arr,'tpl'=>&$this];
}
public function decl_p($inp)
{
$inp = MP_ARR::FROM_STR($inp);
while ($r = array_shift($inp)) $this->declare_parts[$r]=1;
}
public function js4part($p,$f,$EOL=false,$pre="",$glued=1)
{
if (ST_GLUE && $glued) return $this->glue_reg('js',$p,$f);
return $this->st4p($p,$this->js($f),$EOL,$pre);
}
public function css4part($p,$f,$EOL=false,$pre="",$glued=1)
{
if (ST_GLUE && $glued) return $this->glue_reg('css',$p,$f);
return $this->st4p($p,$this->css($f),$EOL,$pre);
}
public function glue_reg($type,$p,$url)
{
$path = str_replace('/mp_pub',SYSDIR."PUB", $url);
$path = str_replace('/pub_data',WEBDIR."pub_data", $path);
switch ($type) {
case 'css':
$path = str_replace('.css','.min.css',$path);
break;
case 'js':
$path = str_replace('.js','.min.js',$path);
break;
}
$this->glue_arr[$type][] =
['u'=>$url,'p'=>$path,'l'=> ((int)$this->if_decl_p($p))];
}
public function glue_stat()
{
$js_k = $css_k = "";
if (!ST_GLUE) return;
foreach ($this->glue_arr['js'] as $key => $it) $js_k.=$it['l'];
foreach ($this->glue_arr['css'] as $key => $it) $css_k.=$it['l'];
$alph = [0,1,2,3,4,5,6,7,8,9,'A','B','C','D','E','F','G','H','I','J','K',
'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','_','-','='];
$js_k = int2alphabet($alph,bindec($js_k));
$css_k = int2alphabet($alph,bindec($css_k));
$glue_path = WEBDIR."pub_data/static_cache/";
$js_path = $glue_path.$js_k.".js";
$css_path = $glue_path.$css_k.".css";
$glue_path = $alph = NULL;
unset($glue_path,$alph);
if (!is_file($js_path) && count($this->glue_arr['js']))
{
foreach ($this->glue_arr['js'] as $key => $it)
{
if (!$it['l']) continue;*/
//$pre = '/* file: '.$it['u'].'*/'."\n";
/* file_put_contents($js_path,$pre.file_get_contents($it['p'])."\n",FILE_APPEND);
}
}
if (!is_file($css_path) && count($this->glue_arr['css']))
{
foreach ($this->glue_arr['css'] as $key => $it)
{
if (!$it['l']) continue;*/
//$pre = '/* file: '.$it['u'].'*/'."\n";
/*file_put_contents($css_path,$pre.file_get_contents($it['p'])."\n",FILE_APPEND);
}
}
$this->to_head($this->css('/pub_data/static_cache/'.$css_k.".css",1));
$js_block = ($this->js2bottom) ? 'bottom_js' : 'head_objects';
$this->add2block($js_block,$this->js('/pub_data/static_cache/'.$js_k.".js",1));
}
public function st4p ($p,$inc,$EOL=false,$pre="")
{
if($this->if_decl_p($p)) return $pre.$inc.(($EOL)?$EOL:'');
}
public function st_format($inp,$pre="",$EOL="")
{
preg_match_all('!(\<[^>]+\>)!simu',$inp,$res);
foreach ($res[1] as $key => $v) echo $pre.$v.$EOL;
}
public function undecl_p($inp)
{
if($this->if_decl_p($inp)) unset($this->declare_parts[$inp]);
}
public function if_decl_p($inp)
{
if ($inp===0) return true;
return (isset($this->declare_parts[$inp]));
}
//+++добавить несколько частей в массиве
public function part_css($part,$css)
{
if ($this->if_decl_p($part))
echo $this->css($css);
}
public function display($prefix=false,$tpl_name="default")
{
global $tpl,$config,$db;
if (LST_TPL) echo_arr($this->load_tpls);
if (arr_v($_POST,'clear')=='yes') $this->clear=1;
if($prefix===false) $prefix = $this->prefix;
if ($this->clear)
{
echo $this->tpl_arr['text'];
return ($this->clear=0);
}
$tpl_arr = &$this->tpl_arr;
include($this->path($tpl_name,$prefix));
if (DBG_MGS) include($this->path('debug_message','default'));
return 1;
}
public function path($tpl_name,$prefix=false)
{
$p = ((empty($prefix))?$this->prefix:$prefix).DS.$tpl_name.'.tpl';
if (is_file($p_=TPLDIR2.$p) || is_file($p_=TPLDIR1.$p))
return str_replace('//','/',$p_);
exit($tpl_name.' - NOT FOUND!!!');
}
public function add2block($k,$v){
$this->tpl_arr[$k] = (isset($this->tpl_arr[$k]))? $this->tpl_arr[$k]."\r\n".$v : $v;
return $this;
}
public function canonical($url)
{
$this->to_head('<link rel="canonical" href="'.$url.'" />');
}
public function show_bl($n)
{
if (isset($this->tpl_arr[$n])) echo $this->tpl_arr[$n];
}
public function css($p,$nm=0)
{
return '<link rel="stylesheet" type="text/css" href="'.$this->p2min($p,$nm,'css').'?v='.MP_VER.'" />';
}
public function js($p,$nm=0)
{
return '<script src="'.$this->p2min($p,$nm,'js').'?v='.MP_VER.'"></script>';
}
public function to_head($str)
{
return $this->add2block('head_objects',$str);
}
public function add_js ($inp,$no_mod=0){
return $this->to_head($this->js($inp,$no_mod));
}
public function add_css ($inp,$no_mod=0){
return $this->to_head($this->css($inp,$no_mod));
}
public function mp_css($inp)
{
$inp = MP_ARR::FROM_STR($inp);
for ($i=0,$c=count($inp); $i < $c; $i++)
$this->add_css(M_PUB.'/css/'.$inp[$i]);
return $this;
}
public function mp_js($inp)
{
$inp = MP_ARR::FROM_STR($inp);
for ($i=0,$c=count($inp); $i < $c; $i++)
$this->add_js(M_PUB.'/js/'.$inp[$i]);
return $this;
}
public function meta_tags ($i,$i2=false)
{
if ($i===false && is_array($i2))
{
$i=[];
list($i['meta_title'],$i['meta_keywords'],$i['meta_description']) = $i2;
}
$f = function($n) {return(htmlspecialchars($n));};
$m_arr = SELECT_FROM_ARR('meta_description;meta_keywords',$i);
$m_arr = array_map($f,$m_arr);
//титл не экранируем
$m_arr['meta_title'] = $i['meta_title'];
unset($i);
$this->tpl_arr = array_merge($this->tpl_arr,$m_arr);
//echo_arr($m_arr);
unset($f,$m_arr);
}
public function ograph($title,$description,$image,$url,$type="website")
{
$a = &$this->tpl_arr;
$a['_html_'] = ' prefix="og: http://ogp.me/ns#"';
$_arr = compact('title','type','url','description','image');
foreach ($_arr as $p => $v)
{
$v=htmlspecialchars($v);
$this->to_head('<meta property="og:'.$p.'" content="'.$v.'"/>');
}
}
public function fetch($t,&$vars=array(),$prefix=false,$cache_en=false)
{
if ($cache_en)
{
$cache_key = MPCACHE::gen_key_p(array($t,$vars,$prefix));
$cache = MPCACHE::from_cache("tpl_cache",$cache_key);
if($cache!==false) return $cache['content'];
}
if (empty($t)||(mb_substr($t,0,1)=="#")) return '';
if (is_array($this->vars))extract($this->vars);
if (is_array($vars))extract($vars);
$tpl = &$this;
$this->load_tpls[] = $__p = $this->path($t,$prefix);
ob_start();
include($__p);
if ($cache_en)
{
$html = ob_get_clean();
MPCACHE::to_cache("tpl_cache",$cache_key,['content'=>$html]);
return $html;
}
return ob_get_clean();
}
public function txt($txt){$this->add2block('text',$txt);}
}
*/

View File

@@ -0,0 +1,36 @@
# LE\_FS - класс для работы с файловой системой и файлами
## GEN\_FNAME($inp\_name, $path, $prefix);
example
```
LE_FS::GEN_FNAME("picture.png",WEBDIR."/pub_data/","prod_");
```
Генерирует уникальное имя файла для указанной папки, расширение нового файла соответствует расширению входного в `$inp_name`
Опционально к имени файла в начале пристыковывается в префикс, например `prod_` `cat_` ...
***
## Apply2Files($path,&$func,$recouse=0)
> Данная функция создана для обработки массива данных
```
LE_FS::Apply2Files("./inp_folder/",$callback,0);
```
* `$path` \- путь до папки
* `$func` \- callback функция в которую передается полный путь до файла
* `$recourse` \- признак рекурсивности\, по умолчанию применяется только к указанной папке\, но если указан флаг то пройдет по всем подпапкам
>Внутри callback функции нужно предусматривать фильтрацию по расширению файла, например только xml или только jpg...
>
## SAVE_POST($inp,&$debug=false) - сохранение файла из POST
Сохраняет файл переданный в POST с указанным именем поля формы в POST в указанную папку `<input type="file" name="img_file">`
```
LE_FS::SAVE_POST(['f_name'=>'img_file','path'=>'/www/path/'])
```
Уникальное имя файлов генерируется автоматически...

133
LE/core.php Normal file
View File

@@ -0,0 +1,133 @@
<?php
/******************
* LE Core *
*****************/
/*core functions*/
function arr_v($arr,$field,$default=false)
{
return isset($arr[$field]) ? $arr[$field] : $default;
}
function echo_arr(&$arr) {
if (ISWEB) echo '<pre>';
print_r($arr);
if (ISWEB) echo '</pre>';
}
/*core class*/
class LE
{
public static $DB,$TPL,$CACHE,$QUERY_DATA_TYPE;
public static function DEF ($constant_name,$val=false)
{
if (!defined($constant_name)) define($constant_name, $val);
}
}
/*date prepare class*/
//prepare class
class PRE {
public static $MASK = ['D' => '0-9', 'R' => 'а-яё', 'L' => 'a-z', 'S' => '\s'];
public static $SH_MASK = [
'UP' => MB_CASE_UPPER,
'DOWN' => MB_CASE_LOWER,
'U1' => MB_CASE_TITLE];
public static function SQL($s)
{
if (method_exists(LE::$DB, 'prepare')) return LE::$DB->prepare($s);
return addslashes($s);
}
public static function DOWN($s)
{
return mb_convert_case($s, MB_CASE_LOWER);
}
public static function UP($s)
{
return mb_convert_case($s, MB_CASE_UPPER);
}
public static function SHIFT($s, $t)
{
if (isset(PRE::$SH_MASK[$t])) {
return mb_convert_case($s, PRE::$SH_MASK[$t]);
}
exit('shift err mask');
}
public static function f2int($n,int $m):int
{
if (empty($n)) return 0;
$n=(float)$n;
$n*=pow(10,$m+1);
return (int) Ceil(round($n)/10);
}
public static function F($s, $t) {
$preg = strtr(preg_quote(trim($t), '!'), PRE::$MASK);
return preg_replace('![^' . $preg . ']!iu', '', $s);
}
public static function UP1($s) {
$s = PRE::SHIFT(trim($s),'DOWN');
$w = preg_split('/\s+/', $s);
if (isset($w[0]))
{
$w[0] = PRE::SHIFT($w[0],'U1');
return implode(' ',$w);
}
return $s;
}
public static function INT($i):int {return (int)PRE::NUM($i);}
public static function NUM($i) {return preg_replace('![^0-9]!', '', $i);}
public static function DEC($i):float {
$i= preg_replace('/[^\-0-9,.]/u', '', $i);
return (float)preg_replace('!([\-]?[0-9]+)[,.]?([0-9]+)?!', '$1.$2', $i);
}
public static function MONEY_OUT($i) {return money_format('%n', $i);}
//удаляет двойные пробелы и табы
public static function DSP($i)
{
return preg_replace('/\s{1,}/u', " ", $i);
}
public static function PLAIN_FORMAT($str,$one_str=0)
{
$str = PRE::DSP($str);
if ($one_str) $str = preg_replace('!([\n]*)!simu', '', $str);
$str = preg_replace('![\s]*([,.])!simu', '$1', $str);
$str = trim($str);
return $str;
}
//подрезает строку по разрешенному лимиту
public static function CROP($s,$l=0){return (($l>0)?mb_substr($s,0,$l):$s);}
}
/**приведение в алфавит $a числа $int */
function int2alphabet(array $a,int $int):string
{
$cnt = count($a); //емкость алфавита
$out="";
while ($int>=$cnt)
{
$out = ($a[($int % $cnt)]).$out;
$int = intdiv($int, $cnt);
}
return $a[$int].$out;
}

5
LE/core_fuctions.md Normal file
View File

@@ -0,0 +1,5 @@
# Описание базовых
>jjj
>kkk
>

5
LE/db_init.php Normal file
View File

@@ -0,0 +1,5 @@
<?php
if (SYSCONF::$USE_MYSQL)
LE::$DB = new LE_MYSQL(SYSCONF::$DB);
//+++add sqlite

11
LE/deprecated.php Normal file
View File

@@ -0,0 +1,11 @@
<?php
if (! function_exists("array_key_last")) {
function array_key_last($array) {
if (!is_array($array) || empty($array)) {
return NULL;
}
return array_keys($array)[count($array)-1];
}
}

14
LE/load_mod.php Normal file
View File

@@ -0,0 +1,14 @@
<?php
$le_mod_loader = new LE_MOD_LOAD();
LE::$QUERY_DATA_TYPE = LE_REQUEST::TYPE_DETECT();
//init space
if ($le_mod_loader->init_path!==false)
include $le_mod_loader->init_path;
//load mod
if ($le_mod_loader->mod_path!==false)
include $le_mod_loader->mod_path;
//not found
if ($le_mod_loader->mod_path==false)
include $le_mod_loader->select_path('main','__404.php');

19
LE/session.php Normal file
View File

@@ -0,0 +1,19 @@
<?php
ini_set('session.gc_maxlifetime', SYSCONF::$SESS_TIME);
ini_set('session.cookie_lifetime', SYSCONF::$SESS_TIME);
ini_set('session.save_path', SYSCONF::$SESS_DIR);
if (!is_dir(SYSCONF::$SESS_DIR)) mkdir(SYSCONF::$SESS_DIR,0700,true);
session_start();
//при первом входе знать откуда пришел человек
if (!isset($_SESSION['ref']) && isset($_SERVER["HTTP_REFERER"]))
$_SESSION['ref'] = $_SERVER["HTTP_REFERER"];
//каждые 3 минуты делаем обновление времени жизни сессии
$_exp = time()+SYSCONF::$SESS_TIME;
if (!isset($_SESSION['_exp']))
$_SESSION['_exp'] = $_exp;
elseif (($_exp-$_SESSION['_exp'])>180)
setcookie ("PHPSESSID", session_id() , ($_SESSION['_exp']=$_exp) ,'/');

6
LE/sys_autoload.php Normal file
View File

@@ -0,0 +1,6 @@
<?php
/* LE Framework autoload core classes */
spl_autoload_register(function ($class_name)
{
if (is_file(CORE_CLSDIR.$class_name.".php")) include CORE_CLSDIR.$class_name.".php";
});

38
LE/sys_conf.php Normal file
View File

@@ -0,0 +1,38 @@
<?php
if(!defined("I")) die('err c001');
if(setlocale(LC_ALL, 'ru_RU.UTF-8','Russian_Russia.65001')===false)
exit('!!!not find UTF-8 LOCALE');
if(setlocale(LC_NUMERIC, 'en_US.UTF-8', 'C.UTF-8','C')===false)
exit('!!!not find C NUMERIC LOCALE');
mb_internal_encoding("UTF-8");
date_default_timezone_set('UTC');
LE::DEF('NO_CACHE'); //по-умолчанию кеширование включено
class SYSCONF
{
public static $DEFAULT_MODSPACE = "main";
public static $DEFAULT_MODULE = ['main' => 'welcome','admin'=>'dashboard'];
public static $MOD_ALIASES;
public static $USE_MYSQL = TRUE;
public static $USE_TPL = TRUE;
public static $ADMIN_MAIL = '';
public static $ROBOT_MAIL = '';
public static $DISP_TIME = FALSE;
public static $DB = ['host'=>'localhost','user'=>'','pass'=>'','db_name' =>''];
public static $SPACE_LIST=['admin|cabinet'=>'admin','main'=>'main'];
public static $SESS_DIR;
public static $SESS_TIME=120960;
public static $MPV;
public static $DR_N="LE CMS";
public static $CACH_DIR;
}
SYSCONF::$SESS_DIR = APPDIR.'sessions'.DS;
SYSCONF::$CACH_DIR = APPDIR.'cache'.DS;
if (is_file(APPDIR.'app_conf.php')) include APPDIR.'app_conf.php';

View File

@@ -0,0 +1,3 @@
<?php
LE::$TPL->prefix="admin";

94
MODULES/admin/blog.php Normal file
View File

@@ -0,0 +1,94 @@
<?php
class CONTR extends LE_MOD_CONTROLLER {
protected function check_dest_folder($f)
{
if (!is_dir($uploaddir))
if(mkdir($uploaddir,0777,true)===false)
return false;
return true;
}
protected function _ajx_add_img($data)
{
if (!isset($_FILES['upload'])) return false;
$dest = WEBDIR.'pub_data/upload/img/';
if (!$this->check_dest_folder($dest)) return false;
$filename = LE_FS::SAVE_POST(['f_name'=>'upload','path'=>$dest]);
return ['url'=>'/pub_data/upload/img/'.$filename, 'as_is'=>1];
}
protected function _ajx_save_content($data)
{
$id = PRE::INT($data['id']);
$html_cont = $data['html_cont'];
preg_match('!(<h1>(.*?)<\/h1>)?(.*)!simu',$html_cont,$out);
$html_cont = $out[3];
$html_head = trim($out[2]);
//return;
$save_data = ['id'=>$id,'html'=>$html_cont,'head'=>$html_head];
$id = LE::$DB->SAVE('text_content',$save_data);
return $id;
}
protected function _ajx_remove_it($inp)
{
if (!isset($inp['id'])) return false;
$id=PRE::INT($inp['id']);
if (!$id>0) return false;
$res = LE::$DB->DEL('text_content',$id);
return ($res>0);
}
protected function _inp_default($inp)
{
$res = LE::$DB->query_arr("SELECT * FROM `text_content`",'id');
$to_tpl['cont_list'] = $res;
return LE::$TPL->fetch('blog/list',$to_tpl);
}
protected function _inp_edit($inp)
{
$id = PRE::INT($inp);
if ($id>0)
{
$res = LE::$DB->query_single("SELECT * FROM `text_content` WHERE `id`=".$id);
$it_data = json_decode($res['data'],1);
}
else
{
$res = ['html'=>'','head'=>''];
$it_data = [];
$id=0;
}
$to_tpl = [
'data'=>$it_data,
'id'=>$id,
'html_cont'=>$res['html'],
'head'=>$res['head']
];
return LE::$TPL->fetch('blog/edit_item',$to_tpl);
}
}
include CLSDIR."blog.php";
$blog_model = new blog_model;
$controller = new CONTR($le_mod_loader->url,$blog_model);
LE::$TPL->mod_cont .= $controller->start();

3
MODULES/main/__404.php Normal file
View File

@@ -0,0 +1,3 @@
<?php
http_response_code(404);
echo "<h1>PAGE NOT FOUND</h1>";

View File

View File

@@ -0,0 +1,68 @@
<?php
class CONTR extends LE_MOD_CONTROLLER {
protected function _ajx_upload_img($data)
{
if (!isset($_FILES['upl_img'])) return false;
$uploaddir = WEBDIR.'pub_data/upload/img/';
if (!is_dir($uploaddir))
if(mkdir($uploaddir,0777,true)===false)
return false;
$filename = LE_FS::SAVE_POST(['f_name'=>'upl_img','path'=>$uploaddir]);
return ['url'=>'/pub_data/upload/img/'.$filename];
}
protected function _ajx_save_content($data)
{
$md_cont = $data['md_cont'];
$id = PRE::INT($data['id']);
$_data = json_encode(['md_cont'=>$md_cont]);
$html_cont = $data['html_cont'];
$save_data = ['id'=>$id,'data'=>$_data,'html'=>$html_cont];
$id = LE::$DB->SAVE('text_content',$save_data);
return $id;
}
protected function _inp_default($inp)
{
$res = LE::$DB->query_arr("SELECT * FROM `text_content`",'id');
$to_tpl['cont_list'] = $res;
return LE::$TPL->fetch('le_ui_kit/editor_list',$to_tpl);
}
protected function _inp_edit($inp)
{
$id = PRE::INT($inp);
if (!$id>0) return false;
$res = LE::$DB->query_single("SELECT * FROM `text_content` WHERE `id`=".$id);
$it_data = json_decode($res['data'],1);
$to_tpl = compact('it_data','res','id');
$to_tpl['md_cont'] = (isset($it_data['md_cont'])) ? $it_data['md_cont'] : '';
return LE::$TPL->fetch('le_ui_kit/test_ckeditor',$to_tpl);
//return LE::$TPL->fetch('le_ui_kit/test_editor',$to_tpl);
}
}
//echo_arr($le_mod_loader->url);
$controller = new CONTR($le_mod_loader->url);
//$mod_out = $controller->start();
LE::$TPL->mod_cont .= $controller->start();

0
MODULES/main/shop.php Normal file
View File

View File

@@ -0,0 +1,191 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>LE UIKit</title>
<link rel="stylesheet" type="text/css" href="/assets/css/le_uikit.css" />
<meta name="viewport" content="width=device-width,initial-scale=1">
<?/*
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js" integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script>
<link rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
*/?>
<link rel="stylesheet"
href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js"></script>
<link rel="stylesheet" href="/pub/css/le_form.css">
<script src="https://cdn.ckeditor.com/ckeditor5/27.1.0/classic/ckeditor.js"></script>
<!-- Editor's Dependecy Style -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/codemirror.min.css"
/>
<!-- Editor's Style -->
<link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor.min.css" />
</head>
<body>
<div id="page_cont" style="max-width:1000px;margin:10px auto;padding:10px;">
<button type="button" class="btn btn-primary">Button</button>
<form class="le_form le_shadow">
<span class="le_form_head">Заголовок формы</span>
<div class="le_he">
<label for="inp_name" class="le_fl"><span>Горизонтальный инпут</span></label>
<div class="le_inp"><input type="text" value="kokoko" id="inp_name"></div>
</div>
<div class="le_ve">
<label for="inp_name" class="le_fl"><span>Вертикальный инпут</span></label>
<div class="le_inp"><input type="text" value="kokoko" id="inp_name"></div>
</div>
<div class="le_he">
<label for="inp_name" class="le_fl"><span>Горизонтальный инпут у которого допустим пару строчек, строчки тут две <sup>*</sup></span></label>
<div class="le_inp"><input type="text" value="kokoko" id="inp_name"></div>
</div>
<div class="le_he">
<div for="select_koko" class="le_fl"><span>Горизонтальный селект</span></div>
<div class="le_inp">
<select id="select_koko">
<option>select</option>
<option>select</option>
<option>select</option>
<option>select</option>
<option>select</option>
</select>
</div>
</div>
<div class="le_he le_me">
<div for="inp_name" class="le_fl"><span>Радиокнопки</span></div>
<div class="le_inp">
<label><input type="radio" name="radio1">Radio1</label>
<label><input type="radio" name="radio1">Radio2</label>
</div>
</div>
<div class="le_ve le_me">
<div for="inp_name" class="le_fl"><span>Радиокнопки вертикально</span></div>
<div class="le_inp">
<label><input type="radio" name="radio1">Radio1</label>
<label><input type="radio" name="radio1">Radio2</label>
</div>
</div>
<div class="le_he le_me">
<div for="inp_name" class="le_fl"><span>Чекбоксы<sup>*</sup></span></div>
<div class="le_inp">
<label><input type="checkbox" name="checkbox1">checkbox1</label>
<label><input type="checkbox" name="checkbox1">checkbox2</label>
</div>
</div>
<div class="le_he le_me le_meh">
<div for="inp_name" class="le_fl"><span>Радиокнопки в линию</span></div>
<div class="le_inp">
<label><input type="radio" name="radio1">Radio1</label>
<label><input type="radio" name="radio1">Radio2</label>
</div>
</div>
<div class="le_he">
<label for="inp_name" class="le_fl"><span>Дата <sup>*</sup></span></label>
<div class="le_inp"><input type="date" value="kokoko" id="inp_name"></div>
</div>
<div class="le_ve">
<label for="inp_name" class="le_fl"><span>Текст</span></label>
<div class="le_inp"><textarea class="cktxt">тролололо</textarea></div>
</div>
<div class="le_he">
<label for="inp_name" class="le_fl"><span>Текст горизонтально</span></label>
<div class="le_inp"><textarea>тролололо</textarea></div>
</div>
<div class="le_ve">
<label for="inp_name" class="le_fl"><span>Текст</span></label>
<div class="le_inp"><textarea class="tu-editor">тролололо</textarea></div>
</div>
<div class="le_bbl">
<button type="submit">Сохранить</button>
<button class="le_btn_blue" type="submit">Синяя</button>
<button class="le_btn_red" type="submit">Красная</button>
<button class="le_btn_green" type="submit">Зеленая</button>
</div>
</form>
<br>
<br>
<br>
<br>
<h2>Markdown Editor from ToastUI</h2>
<div id="editor"></div>
<a href="#" onclick="alert(editor.getHtml()); return false;">html get</a> |
<a href="#" onclick="alert(editor.getMarkdown()); return false;">markdown get</a> |
<a href="#" onclick="hljs.highlightAll(); return false;">Code hilight</a> |
</div>
<script>
/*ClassicEditor
.create( document.querySelector( '.cktxt' ) )
.then( editor => {
console.log( editor );
} )
.catch( error => {
console.error( error );
} );
*/
</script>
<script src="https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js"></script>
<script>
const editor = new toastui.Editor({
el: document.querySelector('#editor'),
previewStyle: 'vertical',
height: '500px',
initialValue: '### hello world \n```\n<?="<?"?>php\n```'
});
editor.on('change',function(e){
/*hljs.highlightAll();*/
document.querySelectorAll('div.te-preview pre').forEach(block => {
// then highlight each
hljs.highlightBlock(block);
});
});
</script>
</body>
</html>

33
MODULES/main/ui_test.php Normal file
View File

@@ -0,0 +1,33 @@
<?php
/*
1. Подключить нужные для модуля классы и конфиги
2. Определить какой метод контроллера выполнить и запустить его
3. Внутри метода идет вывод или запись данных, при выводе передается в шаблон
4. Содержимое
*/
//compute
//if (isset($_POST)) echo_arr($_POST);
//if (isset($_FILES)) echo_arr($_FILES);
if (isset($_FILES['upl_img']))
{
$uploaddir = WEBDIR.'pub_data/upload/img/';
$f_name=basename($_FILES['upl_img']['name']);
$uploadfile = $uploaddir . basename($_FILES['upl_img']['name']);
if (move_uploaded_file($_FILES['upl_img']['tmp_name'], $uploadfile))
{
$out = ['success'=>1];
$out['data'] = ['url'=>'/pub_data/upload/img/'.$f_name];
$mod_out = json_encode($out);
}
}
else
$mod_out = LE::$TPL->fetch('le_ui_kit/test1');
//out to tpl
LE::$TPL->mod_cont .= $mod_out;

1
MODULES/main/welcome.php Normal file
View File

@@ -0,0 +1 @@
Добро пожаловать в новый мир!!!

View File

275
PUB/css/le_form.css Normal file
View File

@@ -0,0 +1,275 @@
/*sys*/
body {
font-family: sans-serif;
}
/*reset form*/
input, select, button, textarea {
border:1px solid #b8b8b8;
border-radius: 0;
-webkit-border-radius: 0px;
border-radius:0;
padding:1px 5px;
height: 40px;
box-sizing: border-box;
font-family: inherit;
font-size:16px;
}
textarea {
min-height: 200px;
padding:8px 8px;
}
select {
-webkit-appearance: none;
-moz-appearance: none;
padding-right: 20px;
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2224%22%20height%3D%2216%22%20viewBox%3D%220%200%2024%2016%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%3Cpolygon%20fill%3D%22%23666%22%20points%3D%2212%201%209%206%2015%206%22%20%2F%3E%0A%20%20%20%20%3Cpolygon%20fill%3D%22%23666%22%20points%3D%2212%2013%209%208%2015%208%22%20%2F%3E%0A%3C%2Fsvg%3E%0A")
,
linear-gradient(to bottom, #ffffff 0%,#ffffff 100%);
background-repeat: no-repeat;
/*background-position: 100% 50%;*/
background-size: 30px auto, 100%;
background-position: right -5px top 50%, 0 0;
}
input[type=radio], input[type=checkbox]
{
display: inline-block;
height: 16px;
width: 16px;
overflow: hidden;
margin-top: -1px;
vertical-align: middle;
-webkit-appearance: none;
-moz-appearance: none;
background-color: transparent;
background-repeat: no-repeat;
background-position: 50% 50%;
border: 1px solid #ccc;
transition: .2s ease-in-out;
transition-property: all;
transition-property: background-color,border;
margin-right: 4px;
}
input[type=radio] {
border-radius: 50%;
margin-top: -4px;
}
input[type=radio]:checked {
background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%3Ccircle%20fill%3D%22%23fff%22%20cx%3D%228%22%20cy%3D%228%22%20r%3D%222%22%20%2F%3E%0A%3C%2Fsvg%3E");
background-color: #1e87f0;
border-color: transparent;
background-size: 30px auto;
}
input[type=checkbox]:checked {
background-image: url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2214%22%20height%3D%2211%22%20viewBox%3D%220%200%2014%2011%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%3Cpolygon%20fill%3D%22%23fff%22%20points%3D%2212%201%205%207.5%202%205%201%205.5%205%2010%2013%201.5%22%20%2F%3E%0A%3C%2Fsvg%3E%0A");
background-color: #1e87f0;
border-color: transparent;
}
input:focus:not([type="checkbox"]):not([type="radio"]), select:focus, textarea:focus {
outline: none;
border-color:#70aae4;
box-shadow: inset 0 0 3px -2px #117de9;
}
/*form blocks style*/
.le_form {
display: block;
overflow: hidden;
margin: 10px 0;
padding:25px;
color:#555;
}
.le_form_head {
display: block;
font-size: 150%;
padding-bottom: 10px;
border-bottom: 1px solid #d9d9d9;
margin-bottom: 20px;
}
.le_shadow {
box-shadow: 0 2px 10px rgba(94, 94, 94, 0.08);
border:1px solid #ececec;
}
.le_he .le_inp {
margin-left:300px;
}
.le_fl {
font-size: 14px;
}
.le_he .le_fl {
width:290px;
float:left;
display: flex;
align-items: center;
min-height: 40px;
}
.le_he, .le_ve {
margin-bottom: 25px;
overflow: hidden;
border-bottom: 1px solid #e9e9e9;
padding-bottom: 25px;
}
.le_ve .le_fl {
margin-bottom: 3px;
display: block;
}
.le_inp input:not([type="checkbox"]):not([type="radio"]),
.le_inp select,
.le_inp textarea
{
max-width: 100%;
width:100%;
}
/*le multi elements*/
.le_me label{
display: block;
padding-top:8px;
}
/*Multi Element Horizontal*/
.le_meh label{
float:left;
margin-right:10px;
}
.le_he {
display:flex;
flex-wrap: wrap;
}
.le_he .le_fl {
min-width: 200px;
flex:40%;
flex-grow: 1;
}
.le_he .le_inp {
margin-left:0;
flex-grow: 1; /*растягиваться на свободное пространство*/
min-width: 200px;
flex:60%;
}
.le_fl sup {
color:red;
font-size: 17px;
font-weight: bold;
padding-left: 2px;
}
/*buttons*/
.le_btn {
display: inline-block;
font-weight: 400;
text-align: center;
white-space: nowrap;
vertical-align: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 1px solid #c9c9c9;
padding: .375rem .75rem;
font-size: 1rem;
line-height: 1.5;
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
background-color: #f9f9f9;
background: linear-gradient(to bottom, #f9f9f9,#f9f9f9);
}
.le_btn:hover {
background: linear-gradient(to bottom, #f9f9f9,#f3f3f3);
border-color:#b5b5b5;
}
/*гамбургеры и крестики*/
#nav-icon6 {
width: 60px;
height: 45px;
position: relative;
transition-duration: 1s;
margin: 48px auto 12px auto;
cursor: pointer;
}
#nav-icon6 span {
height: 9px;
width: 60px;
background-color: #337AB7;
border-radius: 20px;
position: absolute;
transition-duration: .25s;
transition-delay: .25s;
}
#nav-icon6 span:before {
left: 0;
position: absolute;
top: -18px;
height: 9px;
width: 60px;
background-color: #337AB7;
content: "";
border-radius: 20px;
transition-duration: .25s;
transition: transform .25s, top .25s .25s;
}
#nav-icon6 span:after {
left: 0;
position: absolute;
top: 18px;
height: 9px;
width: 60px;
background-color: #337AB7;
content: "";
border-radius: 20px;
transition-duration: .25s;
transition: transform .25s, top .25s .25s;
}
#nav-icon6.open span {
transition-duration: 0.1s;
transition-delay: .25s;
background: transparent;
}
#nav-icon6.open span:before {
transition: top .25s, transform .25s .25s;
top: 0px;
transform: rotateZ(-45deg);
}
#nav-icon6.open span:after {
transition: top 0.4s, transform .25s .25s;
top: 0px;
transform: rotateZ(45deg);
}

1
PUB/css/le_form.min.css vendored Normal file
View File

@@ -0,0 +1 @@
body{font-family:sans-serif}button,input,select,textarea{border:1px solid #b8b8b8;border-radius:0;-webkit-border-radius:0;border-radius:0;padding:1px 5px;height:40px;box-sizing:border-box;font-family:inherit;font-size:16px}textarea{min-height:200px;padding:8px 8px}select{-webkit-appearance:none;-moz-appearance:none;padding-right:20px;background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2224%22%20height%3D%2216%22%20viewBox%3D%220%200%2024%2016%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%3Cpolygon%20fill%3D%22%23666%22%20points%3D%2212%201%209%206%2015%206%22%20%2F%3E%0A%20%20%20%20%3Cpolygon%20fill%3D%22%23666%22%20points%3D%2212%2013%209%208%2015%208%22%20%2F%3E%0A%3C%2Fsvg%3E%0A"),linear-gradient(to bottom,#fff 0,#fff 100%);background-repeat:no-repeat;background-size:30px auto,100%;background-position:right -5px top 50%,0 0}input[type=checkbox],input[type=radio]{display:inline-block;height:16px;width:16px;overflow:hidden;margin-top:-1px;vertical-align:middle;-webkit-appearance:none;-moz-appearance:none;background-color:transparent;background-repeat:no-repeat;background-position:50% 50%;border:1px solid #ccc;transition:.2s ease-in-out;transition-property:all;transition-property:background-color,border;margin-right:4px}input[type=radio]{border-radius:50%;margin-top:-4px}input[type=radio]:checked{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2216%22%20height%3D%2216%22%20viewBox%3D%220%200%2016%2016%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%3Ccircle%20fill%3D%22%23fff%22%20cx%3D%228%22%20cy%3D%228%22%20r%3D%222%22%20%2F%3E%0A%3C%2Fsvg%3E");background-color:#1e87f0;border-color:transparent;background-size:30px auto}input[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg%20width%3D%2214%22%20height%3D%2211%22%20viewBox%3D%220%200%2014%2011%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%3Cpolygon%20fill%3D%22%23fff%22%20points%3D%2212%201%205%207.5%202%205%201%205.5%205%2010%2013%201.5%22%20%2F%3E%0A%3C%2Fsvg%3E%0A");background-color:#1e87f0;border-color:transparent}input:focus:not([type=checkbox]):not([type=radio]),select:focus,textarea:focus{outline:0;border-color:#70aae4;box-shadow:inset 0 0 3px -2px #117de9}.le_form{display:block;overflow:hidden;margin:10px 0;padding:25px;color:#555}.le_form_head{display:block;font-size:150%;padding-bottom:10px;border-bottom:1px solid #d9d9d9;margin-bottom:20px}.le_shadow{box-shadow:0 2px 10px rgba(94,94,94,.08);border:1px solid #ececec}.le_he .le_inp{margin-left:300px}.le_fl{font-size:14px}.le_he .le_fl{width:290px;float:left;display:flex;align-items:center;min-height:40px}.le_he,.le_ve{margin-bottom:25px;overflow:hidden;border-bottom:1px solid #e9e9e9;padding-bottom:25px}.le_ve .le_fl{margin-bottom:3px;display:block}.le_inp input:not([type=checkbox]):not([type=radio]),.le_inp select,.le_inp textarea{max-width:100%;width:100%}.le_me label{display:block;padding-top:8px}.le_meh label{float:left;margin-right:10px}.le_he{display:flex;flex-wrap:wrap}.le_he .le_fl{min-width:200px;flex:40%;flex-grow:1}.le_he .le_inp{margin-left:0;flex-grow:1;min-width:200px;flex:60%}.le_fl sup{color:red;font-size:17px;font-weight:700;padding-left:2px}.le_btn{display:inline-block;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border:1px solid #c9c9c9;padding:.375rem .75rem;font-size:1rem;line-height:1.5;transition:color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;background-color:#f9f9f9;background:linear-gradient(to bottom,#f9f9f9,#f9f9f9)}.le_btn:hover{background:linear-gradient(to bottom,#f9f9f9,#f3f3f3);border-color:#b5b5b5}#nav-icon6{width:60px;height:45px;position:relative;transition-duration:1s;margin:48px auto 12px auto;cursor:pointer}#nav-icon6 span{height:9px;width:60px;background-color:#337ab7;border-radius:20px;position:absolute;transition-duration:.25s;transition-delay:.25s}#nav-icon6 span:before{left:0;position:absolute;top:-18px;height:9px;width:60px;background-color:#337ab7;content:"";border-radius:20px;transition-duration:.25s;transition:transform .25s,top .25s .25s}#nav-icon6 span:after{left:0;position:absolute;top:18px;height:9px;width:60px;background-color:#337ab7;content:"";border-radius:20px;transition-duration:.25s;transition:transform .25s,top .25s .25s}#nav-icon6.open span{transition-duration:.1s;transition-delay:.25s;background:0 0}#nav-icon6.open span:before{transition:top .25s,transform .25s .25s;top:0;transform:rotateZ(-45deg)}#nav-icon6.open span:after{transition:top .4s,transform .25s .25s;top:0;transform:rotateZ(45deg)}

369
PUB/css/reset.css Normal file
View File

@@ -0,0 +1,369 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0-modified | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* make sure to set some focus styles for accessibility */
:focus {
outline: 0;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
input[type=search]::-webkit-search-cancel-button,
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-results-button,
input[type=search]::-webkit-search-results-decoration {
-webkit-appearance: none;
-moz-appearance: none;
}
input[type=search] {
-webkit-appearance: none;
-moz-appearance: none;
-webkit-box-sizing: content-box;
-moz-box-sizing: content-box;
box-sizing: content-box;
}
textarea {
overflow: auto;
vertical-align: top;
resize: vertical;
}
/**
* Correct `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
*/
audio,
canvas,
video {
display: inline-block;
*display: inline;
*zoom: 1;
max-width: 100%;
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address styling not present in IE 7/8/9, Firefox 3, and Safari 4.
* Known issue: no IE 6 support.
*/
[hidden] {
display: none;
}
/**
* 1. Correct text resizing oddly in IE 6/7 when body `font-size` is set using
* `em` units.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-size: 100%; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: thin dotted;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/**
* 1. Remove border when inside `a` element in IE 6/7/8/9 and Firefox 3.
* 2. Improve image quality when scaled in IE 7.
*/
img {
border: 0; /* 1 */
-ms-interpolation-mode: bicubic; /* 2 */
}
/**
* Address margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
*/
figure {
margin: 0;
}
/**
* Correct margin displayed oddly in IE 6/7.
*/
form {
margin: 0;
}
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 1px solid #c0c0c0;
margin: 0 2px;
padding: 0.35em 0.625em 0.75em;
}
/**
* 1. Correct color not being inherited in IE 6/7/8/9.
* 2. Correct text not wrapping in Firefox 3.
* 3. Correct alignment displayed oddly in IE 6/7.
*/
legend {
border: 0; /* 1 */
padding: 0;
white-space: normal; /* 2 */
*margin-left: -7px; /* 3 */
}
/**
* 1. Correct font size not being inherited in all browsers.
* 2. Address margins set differently in IE 6/7, Firefox 3+, Safari 5,
* and Chrome.
* 3. Improve appearance and consistency in all browsers.
*/
button,
input,
select,
textarea {
font-size: 100%; /* 1 */
margin: 0; /* 2 */
vertical-align: baseline; /* 3 */
*vertical-align: middle; /* 3 */
}
/**
* Address Firefox 3+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
border-radius: 0;
border: 1px solid rgb(187, 183, 183);
background: #fff;
}
/**
* Address inconsistent `text-transform` inheritance for `button` and `select`.
* All other form control elements do not inherit `text-transform` values.
* Correct `button` style inheritance in Chrome, Safari 5+, and IE 6+.
* Correct `select` style inheritance in Firefox 4+ and Opera.
*/
button,
select {
text-transform: none;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
* 4. Remove inner spacing in IE 7 without affecting normal text inputs.
* Known issue: inner spacing remains in IE 6.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
*overflow: visible; /* 4 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* 1. Address box sizing set to content-box in IE 8/9.
* 2. Remove excess padding in IE 8/9.
* 3. Remove excess padding in IE 7.
* Known issue: excess padding remains in IE 6.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
*height: 13px; /* 3 */
*width: 13px; /* 3 */
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Remove inner padding and border in Firefox 3+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* 1. Remove default vertical scrollbar in IE 6/7/8/9.
* 2. Improve readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}
html,
button,
input,
select,
textarea {
color: #222;
}
::-moz-selection {
background: #b3d4fc;
text-shadow: none;
}
::selection {
background: #b3d4fc;
text-shadow: none;
}
img {
vertical-align: middle;
}
fieldset {
border: 0;
margin: 0;
padding: 0;
}
textarea {
resize: vertical;
}
.chromeframe {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}

1
PUB/css/reset.min.css vendored Normal file
View File

@@ -0,0 +1 @@
a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}:focus{outline:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:'';content:none}table{border-collapse:collapse;border-spacing:0}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration,input[type=search]::-webkit-search-results-button,input[type=search]::-webkit-search-results-decoration{-webkit-appearance:none;-moz-appearance:none}input[type=search]{-webkit-appearance:none;-moz-appearance:none;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}textarea{overflow:auto;vertical-align:top;resize:vertical}audio,canvas,video{display:inline-block;max-width:100%}audio:not([controls]){display:none;height:0}[hidden]{display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted}a:active,a:hover{outline:0}img{border:0;-ms-interpolation-mode:bicubic}figure{margin:0}form{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline}button,input{line-height:normal;border-radius:0;border:1px solid #bbb7b7;background:#fff}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}button,html,input,select,textarea{color:#222}::-moz-selection{background:#b3d4fc;text-shadow:none}::selection{background:#b3d4fc;text-shadow:none}img{vertical-align:middle}fieldset{border:0;margin:0;padding:0}textarea{resize:vertical}.chromeframe{margin:.2em 0;background:#ccc;color:#000;padding:.2em 0}

0
PUB/css/top_menu.css Normal file
View File

153
PUB/css/txt_cont.css Normal file
View File

@@ -0,0 +1,153 @@
/*text block*/
.txt_cont
{
overflow: hidden;
font-size: 20px;
color:#404040;
}
/*heading*/
.txt_cont h1 {font-size:2em;}
.txt_cont h2 {font-size:1.6em;}
.txt_cont h3 {font-size:1.4em;}
.txt_cont h4 {font-size:1.1em;}
.txt_cont p {
/*text-indent:1em;*/
font-size: 1em;
line-height: 1.5em;
}
/*image*/
.txt_cont img {
display: block;
margin: 0 auto;
max-width: 100%;
min-width: 50px;
}
.txt_cont .image {
display: table;
clear: both;
text-align: center;
margin: 1em auto;
/*border: 1px solid #e6e6e6;*/
box-shadow: 0 0 6px 1px #aeaeae;
}
/*image float*/
.ck-content .image-style-side,
.txt_cont .image-style-side
{
float:right;
margin-left:1.5em;
margin-top:0.2em !important;
}
.txt_cont .image > figcaption {
display:table-caption;
caption-side: bottom;
word-break: break-word;
color: #333;
background-color: #f7f7f7;
padding: .6em;
font-size: .75em;
outline-offset: -1px;
box-shadow: 0 0 6px 1px #aeaeae;
}
.txt_cont figure.table {margin:0;}
/*video*/
.txt_cont .media {
clear: both;
margin: 1em 0;
display: block;
min-width: 15em;
}
.txt_cont figure.table
{
display: table;
}
.ck-content .table table td,
.ck-content .table table th,
.txt_cont .table table td,
.txt_cont .table table th
{
min-width: 2em;
padding: .4em;
border: 1px solid #bfbfbf;
}
.txt_cont table { border-collapse: collapse; width: 100%; }
.ck-content .table table th ,
.txt_cont .table table th
{
font-weight: 700;
background: hsla(0,0%,0%,5%);
}
.txt_cont .table th {
text-align: left;
}
.txt_cont hr {
margin: 15px 0;
height: 4px;
background: #dedede;
border: 0;
}
.txt_cont code {
background-color: hsla(0,0%,78%,.3);
padding: .15em;
border-radius: 2px;
}
.txt_cont pre {
padding: 1em;
color: #353535;
background: hsla(0,0%,78%,.3);
border: 1px solid #c4c4c4;
border-radius: 2px;
text-align: left;
direction: ltr;
tab-size: 4;
white-space: pre-wrap;
font-style: normal;
min-width: 200px;
position: relative;
}
.txt_cont pre code {
background-color: transparent;
}
.txt_cont ul {
list-style-type: disc;
padding-left:18px;
}
.txt_cont blockquote {
overflow: hidden;
padding-right: 1.5em;
padding-left: 1.5em;
margin-left: 0;
margin-right: 0;
font-style: italic;
border-left: 5px solid #ccc;
}

1
PUB/css/txt_cont.min.css vendored Normal file
View File

@@ -0,0 +1 @@
.txt_cont{overflow:hidden;font-size:20px;color:#404040}.txt_cont h1{font-size:2em}.txt_cont h2{font-size:1.6em}.txt_cont h3{font-size:1.4em}.txt_cont h4{font-size:1.1em}.txt_cont p{font-size:1em;line-height:1.5em}.txt_cont img{display:block;margin:0 auto;max-width:100%;min-width:50px}.txt_cont .image{display:table;clear:both;text-align:center;margin:1em auto;box-shadow:0 0 6px 1px #aeaeae}.ck-content .image-style-side,.txt_cont .image-style-side{float:right;margin-left:1.5em;margin-top:.2em!important}.txt_cont .image>figcaption{display:table-caption;caption-side:bottom;word-break:break-word;color:#333;background-color:#f7f7f7;padding:.6em;font-size:.75em;outline-offset:-1px;box-shadow:0 0 6px 1px #aeaeae}.txt_cont figure.table{margin:0}.txt_cont .media{clear:both;margin:1em 0;display:block;min-width:15em}.txt_cont figure.table{display:table}.ck-content .table table td,.ck-content .table table th,.txt_cont .table table td,.txt_cont .table table th{min-width:2em;padding:.4em;border:1px solid #bfbfbf}.txt_cont table{border-collapse:collapse;width:100%}.ck-content .table table th,.txt_cont .table table th{font-weight:700;background:hsla(0,0%,0%,5%)}.txt_cont .table th{text-align:left}.txt_cont hr{margin:15px 0;height:4px;background:#dedede;border:0}.txt_cont code{background-color:hsla(0,0%,78%,.3);padding:.15em;border-radius:2px}.txt_cont pre{padding:1em;color:#353535;background:hsla(0,0%,78%,.3);border:1px solid #c4c4c4;border-radius:2px;text-align:left;direction:ltr;tab-size:4;white-space:pre-wrap;font-style:normal;min-width:200px;position:relative}.txt_cont pre code{background-color:transparent}.txt_cont ul{list-style-type:disc;padding-left:18px}.txt_cont blockquote{overflow:hidden;padding-right:1.5em;padding-left:1.5em;margin-left:0;margin-right:0;font-style:italic;border-left:5px solid #ccc}

6
PUB/js/ckeditor5.js Normal file

File diff suppressed because one or more lines are too long

1
PUB/js/ckeditor5.js.map Normal file

File diff suppressed because one or more lines are too long

5
PUB/js/ckeditor5.min.js vendored Normal file

File diff suppressed because one or more lines are too long

34
PUB/js/le_crud.js Normal file
View File

@@ -0,0 +1,34 @@
le_crud = {
rem: function(id,el_id)
{
u = window.location.href;
el = document.querySelector(el_id);
if (typeof el !=='object') return false;
data = {id:id,method:"remove_it"};
if(!confirm("Удалить статью?")) return false;
fetch(u,
{
method: 'POST',
body: JSON.stringify(data),
headers: {'Content-Type': 'application/json'}
}
).then ((resp)=>{return resp.json()}).then
((resp)=>{
if (!resp.success) {alert('Произошла ошибка!'); return false;}
el.remove();
});
}
}

1
PUB/js/le_crud.min.js vendored Normal file
View File

@@ -0,0 +1 @@
le_crud={rem:function(id,el_id){return u=window.location.href,el=document.querySelector(el_id),"object"==typeof el&&(data={id:id,method:"remove_it"},!!confirm("Удалить статью?")&&void fetch(u,{method:"POST",body:JSON.stringify(data),headers:{"Content-Type":"application/json"}}).then(resp=>resp.json()).then(resp=>{if(!resp.success)return alert("Произошла ошибка!"),!1;el.remove()}))}};

20334
PUB/js/tui-editor.js Normal file

File diff suppressed because one or more lines are too long

28
PUB/js/tui-editor.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,162 @@
<?$tpl->need_static(['-tui-editor','jquery','le_form','ckeditor5','highlight.js','txt_cont'])?>
<a href="/admin/blog">Назад к списку</a>
<h2>Редактор статьи</h2>
<div id="editor" class="txt_cont">
<h1><?=$head?></h1>
<?=$html_cont?>
</div>
<button onclick="save_cont();">Сохранить</button>
<div id="result_cont" class="txt_cont">
load
</div>
<script>
editor = false;
function save_cont()
{
cont_html = editor.getData();
//cont_body = cont_html.getTitle();
//alert(cont_body);
const formData = new FormData();
formData.append('clear', 'yes');
formData.append('ajax', 'yes');
formData.append('mod', 'save_content');
formData.append('data[html_cont]', cont_html);
formData.append('data[id]', <?=$id?>);
fetch('/admin/blog', {method: 'POST',body: formData}).then((resp)=>{return resp.json()}).then(
(resp)=>{
if (!resp.success) return false;
window.location.href="/admin/blog/";
}
);
//alert(response);
//console.log(response);
}
window.addEventListener('load', (event) =>
{
var options = {
toolbar: {
items: [
'bold',
'italic',
'underline',
'strikethrough',
'link',
'subscript',
'superscript',
'-',
'code',
'fontColor',
'removeFormat',
'undo',
'redo'
],
shouldNotGroupWhenFull: true
},
language: 'ru',
blockToolbar: [
'codeBlock',
'horizontalLine',
'htmlEmbed',
'imageUpload',
'imageInsert',
'indent',
'outdent',
'numberedList',
'bulletedList',
'blockQuote',
'mediaEmbed',
'insertTable',
'alignment'
],
image: {
toolbar: [
'imageTextAlternative',
'imageStyle:full',
'imageStyle:side',
'linkImage'
]
},
table: {
contentToolbar: [
'tableColumn',
'tableRow',
'mergeTableCells',
'tableCellProperties',
'tableProperties'
]
},
licenseKey: '',
mediaEmbed: {previewsInData:true},
simpleUpload: {uploadUrl: '/admin/blog'}
};
BalloonBlockEditor
.create( document.querySelector( '#editor' ), options )
.then( editor => {
window.editor = editor;
document.querySelector( '#result_cont' ).innerHTML=editor.getData();
editor.model.document.on( 'change:data', () =>
{
console.log( 'The data has changed!' );
document.querySelector( '#result_cont' ).innerHTML=editor.getData();
}
);
} )
.catch( error => {
console.error( 'Oops, something went wrong!' );
console.error( 'Please, report the following error on https://github.com/ckeditor/ckeditor5/issues with the build id and the error stack trace:' );
console.warn( 'Build id: 9v07c6uegbjg-a3pt58397xor' );
console.error( error );
} );
});
</script>
<style>
#editor,
.txt_cont {
border: 1px solid #d0d0d0;
padding: 20px 30px;
margin-top:40px;
}
</style>

47
TPL/admin/blog/list.tpl Normal file
View File

@@ -0,0 +1,47 @@
<?$tpl->need_static(['-tui-editor','jquery','le_form','ckeditor5','highlight.js','txt_cont','le_crud'])?>
<h2>Список статей</h2>
<a href="/admin/blog/edit:0">Создать</a>
<?foreach($cont_list as $id=>$cont):?>
<div href="/admin/blog/edit:<?=$id?>" class="el_cont" id="el_<?=$id?>">
<h3><a href="/admin/blog/edit:<?=$id?>"><?=empty($cont['head'])?"Статья ".$id: $cont['head']?></a>
<button style="" onclick="le_crud.rem(<?=$id?>,'#el_<?=$id?>')">Удалить</button>
</h3>
<div class="el_cont_content txt_cont">
<?=$cont['html']?>
</div>
</div>
<?endforeach;?>
<style>
.el_cont {
text-decoration:none;
display:block;
color:inherit;
border:1px solid #d0d0d0;
margin: 20px;
padding: 20px;
}
.el_cont:hover {background:#fafafa;}
.el_cont_content {border: 2px dotted #d9d9d9;padding:10px;}
</style>
<script>
window.addEventListener('load', (event) =>
{
document.querySelectorAll('pre code').forEach((block) => {
hljs.highlightElement(block);
});
});
</script>

16
TPL/admin/main.tpl Normal file
View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><?=$tpl->meta['title'];?></title>
<meta name="description" content="<?=$tpl->meta['description'];?>">
<meta name="keywords" content="<?=$tpl->meta['keywords'];?>">
<meta name="viewport" content="width=device-width,initial-scale=1">
<?=$tpl->head_cont;?>
</head>
<body>
<?=$tpl->cont_top;?>
<?=$tpl->fetch('main_body');?>
<?=$tpl->cont_bottom;?>
</body>
</html>

4
TPL/admin/main_body.tpl Normal file
View File

@@ -0,0 +1,4 @@
<!--тут будет шапка и меню...-->
<div class="page_cont" style="max-width:1000px; margin:20px auto;">
<?=$tpl->mod_cont;?>
</div>

66
TPL/admin/static_list.php Normal file
View File

@@ -0,0 +1,66 @@
<?php
$st_cnf = &LE::$TPL->static_list;
$st_dep = &LE::$TPL->static_dep;
$st_cnf[] = [
'mod'=>'highlight.js',
'pos'=>'top',
'type'=>'css',
'link'=>'//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css'];
$st_cnf[] = [
'mod'=>'highlight.js',
'pos'=>'bottom',
'type'=>'js',
'link'=>'//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js'];
$st_cnf[] = [
'mod'=>'le_form',
'type'=>'css',
'link'=>'/pub/css/le_form.css'];
$st_cnf[] = [
'mod'=>'ckeditor5',
'type'=>'js',
'link'=>'/pub/js/ckeditor5.js'];
$st_cnf[] = [
'mod'=>'codemirror',
'type'=>'css',
'link'=>'https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/codemirror.min.css'];
$st_cnf[] = [
'mod'=>'tui-editor',
'type'=>'css',
'link'=>'https://uicdn.toast.com/editor/latest/toastui-editor.min.css'];
$st_cnf[] = [
'mod'=>'tui-editor',
'type'=>'js',
'link'=>'https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js'
//'link'=>'/pub/js/tui-editor.js'
];
$st_cnf[] = [
'mod'=>'jquery',
'type'=>'js',
'link'=>'https://code.jquery.com/jquery-3.6.0.slim.min.js'];
$st_cnf[] = [
'mod'=>'txt_cont',
'type'=>'css',
'link'=>'/pub/css/txt_cont.css'];
$st_cnf[] = [
'mod'=>'embedly',
'type'=>'js',
'link'=>'//cdn.embedly.com/widgets/platform.js'];
$st_cnf[] = [
'mod'=>'le_crud',
'type'=>'js',
'link'=>'/pub/js/le_crud.js'];
$st_dep['tui-editor']=['codemirror','oth'];

View File

@@ -0,0 +1,31 @@
<?$tpl->need_static(['-tui-editor','jquery','le_form','ckeditor5','highlight.js'])?>
<h2>Список статей</h2>
<?foreach($cont_list as $id=>$cont):?>
<a href="/editor_test/edit:<?=$id?>" class="el_cont">
<h3>Статья <?=$id?></h3>
<div class="el_cont_content">
<?=$cont['html']?>
</div>
</a>
<?endforeach;?>
<style>
.el_cont {
text-decoration:none;
display:block;
color:inherit;
border:1px solid #d0d0d0;
margin: 20px;
padding: 20px;
}
.el_cont:hover {background:#fafafa;}
.el_cont_content {border: 2px dotted #d9d9d9;padding:10px;}
</style>

View File

@@ -0,0 +1,213 @@
<?$tpl->need_static(['tui-editor','jquery','le_form','ckeditor5','highlight.js'])?>
<form class="le_form le_shadow">
<span class="le_form_head">Заголовок формы</span>
<div class="le_he">
<label for="inp_name" class="le_fl"><span>Горизонтальный инпут</span></label>
<div class="le_inp"><input type="text" value="kokoko" id="inp_name"></div>
</div>
<div class="le_ve">
<label for="inp_name" class="le_fl"><span>Вертикальный инпут</span></label>
<div class="le_inp"><input type="text" value="kokoko" id="inp_name"></div>
</div>
<div class="le_he">
<label for="inp_name" class="le_fl"><span>Горизонтальный инпут у которого допустим пару строчек, строчки тут две <sup>*</sup></span></label>
<div class="le_inp"><input type="text" value="kokoko" id="inp_name"></div>
</div>
<div class="le_he">
<div for="select_koko" class="le_fl"><span>Горизонтальный селект</span></div>
<div class="le_inp">
<select id="select_koko">
<option>select</option>
<option>select</option>
<option>select</option>
<option>select</option>
<option>select</option>
</select>
</div>
</div>
<div class="le_he le_me">
<div for="inp_name" class="le_fl"><span>Радиокнопки</span></div>
<div class="le_inp">
<label><input type="radio" name="radio1">Radio1</label>
<label><input type="radio" name="radio1">Radio2</label>
</div>
</div>
<div class="le_ve le_me">
<div for="inp_name" class="le_fl"><span>Радиокнопки вертикально</span></div>
<div class="le_inp">
<label><input type="radio" name="radio1">Radio1</label>
<label><input type="radio" name="radio1">Radio2</label>
</div>
</div>
<div class="le_he le_me">
<div for="inp_name" class="le_fl"><span>Чекбоксы<sup>*</sup></span></div>
<div class="le_inp">
<label><input type="checkbox" name="checkbox1">checkbox1</label>
<label><input type="checkbox" name="checkbox1">checkbox2</label>
</div>
</div>
<div class="le_he le_me le_meh">
<div for="inp_name" class="le_fl"><span>Радиокнопки в линию</span></div>
<div class="le_inp">
<label><input type="radio" name="radio1">Radio1</label>
<label><input type="radio" name="radio1">Radio2</label>
</div>
</div>
<div class="le_he">
<label for="inp_name" class="le_fl"><span>Дата <sup>*</sup></span></label>
<div class="le_inp"><input type="date" value="kokoko" id="inp_name"></div>
</div>
<div class="le_ve">
<label for="inp_name" class="le_fl"><span>Текст</span></label>
<div class="le_inp"><textarea class="cktxt">тролололо</textarea></div>
</div>
<div class="le_he">
<label for="inp_name" class="le_fl"><span>Текст горизонтально</span></label>
<div class="le_inp"><textarea>тролололо</textarea></div>
</div>
<div class="le_ve">
<label for="inp_name" class="le_fl"><span>Текст</span></label>
<div class="le_inp"><textarea class="tu-editor">тролололо</textarea></div>
</div>
<div class="le_bbl">
<button class="le_btn" type="submit">Сохранить</button>
<button class="le_btn le_btn_blue" type="submit">Синяя</button>
<button class="le_btn le_btn_red" type="submit">Красная</button>
<button class="le_btn le_btn_green" type="submit">Зеленая</button>
</div>
</form>
<br>
<br>
<br>
<br>
<h2>Markdown Editor from ToastUI</h2>
<div id="editor"></div>
<a href="#" onclick="alert(editor.getHtml()); return false;">html get</a> |
<a href="#" onclick="alert(editor.getMarkdown()); return false;">markdown get</a> |
<a href="#" onclick="hljs.highlightAll(); return false;">Code hilight</a> |
<script>
window.addEventListener('load', (event) =>
{
function uploadImage(blob) {
let formData = new FormData();
formData.append("upl_img", blob, blob.name);
formData.append("opt", 'upload_img');
formData.append("clear", 'yes');
return fetch('/ui_test', {
method: 'POST',
body: formData
}).then(response => {
if (response.ok) {
return response.json();
}
throw new Error('Server or network error');
});
};
function onAddImageBlob(blob, callback) {
uploadImage(blob)
.then(response => {
if (!response.success) {
throw new Error('Validation error');
}
callback(response.data.url, 'alt text');
}).catch(error => {
console.log(error);
});
};
const editor = new toastui.Editor({
el: document.querySelector('#editor'),
previewStyle: 'vertical',
height: '500px',
initialValue: '### hello world \n```\n<?="<?"?>php\n```',
hooks:
{
addImageBlobHook:function(blob, callback)
{
let formData = new FormData();
formData.append("upl_img", blob, blob.name);
formData.append("opt", 'upload_img');
formData.append("clear", 'yes');
fetch('/ui_test', {method: 'POST',body: formData
}).then(resp => resp.json()).then(resp=>{
if (!resp.success) {throw new Error('Validation error');}
callback(resp.data.url, 'alt text');
});
}
}
});
editor.on('change',function(e){
document.querySelectorAll('div.te-preview pre').forEach(block => {hljs.highlightBlock(block);});
});
hljs.highlightAll();
$(function() {
$('#nav-icon6').click(function(){
$(this).toggleClass('open');
});
});
});
</script>
<hr/>
<button class="c-hamburger c-hamburger--rot">
<span>toggle menu</span>
</button>
<button class="c-hamburger c-hamburger--htx">
<span>toggle menu</span>
</button>
<button class="c-hamburger c-hamburger--htla">
<span>toggle menu</span>
</button>
<button class="c-hamburger c-hamburger--htra">
<span>toggle menu</span>
</button>
<div id="nav-icon6">
<span></span>
</div>

View File

@@ -0,0 +1,26 @@
<?$tpl->need_static(['tui-editor','jquery','le_form','ckeditor5','highlight.js'])?>
<a href="/editor_test">Назад к списку</a>
<h2>Редактор статьи</h2>
<div class="txt_cont" id="editor" style="overflow:hidden;">
kokoko
</div>
<script>
window.addEventListener('load', (event) =>
{
ClassicEditor.create( document.querySelector( '#editor' ) )
.catch( error => {
console.error( error );
} );
/* editor.on('change',function(e){
document.querySelectorAll('div.te-preview pre').forEach(block => {hljs.highlightElement(block);});
});*/
hljs.highlightAll();
});
</script>

View File

@@ -0,0 +1,128 @@
<?$tpl->need_static(['tui-editor','jquery','le_form','ckeditor5','highlight.js'])?>
<a href="/editor_test">Назад к списку</a>
<h2>Редактор статьи</h2>
<div id="editor" style="overflow:hidden;"></div>
<a href="#" onclick="alert(editor.getHtml()); return false;">html get</a> |
<a href="#" onclick="alert(editor.getMarkdown()); return false;">markdown get</a>
<button onclick="save_md_cont();">Сохранить</button>
<script>
editor = false;
function save_md_cont()
{
cont_md = editor.getMarkdown();
cont_html = editor.getHtml();
const formData = new FormData();
formData.append('clear', 'yes');
formData.append('ajax', 'yes');
formData.append('mod', 'save_content');
formData.append('data[md_cont]', cont_md);
formData.append('data[html_cont]', cont_html);
formData.append('data[id]', <?=$id?>);
fetch('/editor_test', {method: 'POST',body: formData});
}
window.addEventListener('load', (event) =>
{
editor = new toastui.Editor({
el: document.querySelector('#editor'),
previewStyle: 'vertical',
height: '500px',
<?/*initialValue: "<?=$md_cont?>",*/?>
initialValue: <?=json_encode($md_cont)?>,
hooks:
{
addImageBlobHook:function(blob, callback)
{
let formData = new FormData();
formData.append("upl_img", blob, blob.name);
formData.append("mod", 'upload_img');
formData.append("ajax", 'yes');
fetch('/editor_test', {method: 'POST',body: formData
}).then(resp => resp.json()).then(resp=>{
if (!resp.success) {throw new Error('Validation error');}
callback(resp.data.url, 'alt text');
});
}
},
customHTMLRenderer:
{
image(node, context)
{
const { destination } = node;
const { getChildrenText, skipChildren } = context;
console.log(node);
skipChildren();
return {
type: 'html',
//content: '<figure><img src="'+destination+'"></figure>'
content: '<span><img src="'+destination+'"></span>'
};
/*return [
{
type: 'openTag',
tagName: 'img',
selfClose: true,
attributes: {
src: destination,
alt: getChildrenText(node)+"kokoko",
title: "zhopa"}
}
];*/
return [
{ type: 'openTag', tagName: 'figure'},
{
type: 'openTag',
tagName: 'img',
selfClose: true,
attributes: {
src: destination,
alt: getChildrenText(node)+"kokoko",
title: "zhopa"}
}
,
//{ type: 'openTag', tagName: 'figcaption' },
//{ type: 'text', content: node.title },
//{ type: 'closeTag', tagName: 'figcaption' },
{ type: 'closeTag', tagName: 'figure' }
];
}
}
});
/* editor.on('change',function(e){
document.querySelectorAll('div.te-preview pre').forEach(block => {hljs.highlightElement(block);});
});*/
hljs.highlightAll();
});
</script>

16
TPL/main/main.tpl Normal file
View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><?=$tpl->meta['title'];?></title>
<meta name="description" content="<?=$tpl->meta['description'];?>">
<meta name="keywords" content="<?=$tpl->meta['keywords'];?>">
<meta name="viewport" content="width=device-width,initial-scale=1">
<?=$tpl->head_cont;?>
</head>
<body>
<?=$tpl->cont_top;?>
<?=$tpl->fetch('main_body');?>
<?=$tpl->cont_bottom;?>
</body>
</html>

4
TPL/main/main_body.tpl Normal file
View File

@@ -0,0 +1,4 @@
<!--тут будет шапка и меню...-->
<div class="page_cont" style="max-width:1000px; margin:20px auto;">
<?=$tpl->mod_cont;?>
</div>

53
TPL/main/static_list.php Normal file
View File

@@ -0,0 +1,53 @@
<?php
$st_cnf = &LE::$TPL->static_list;
$st_dep = &LE::$TPL->static_dep;
$st_cnf[] = [
'mod'=>'highlight.js',
'pos'=>'top',
'type'=>'css',
'link'=>'//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css'];
$st_cnf[] = [
'mod'=>'highlight.js',
'pos'=>'bottom',
'type'=>'js',
'link'=>'//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js'];
$st_cnf[] = [
'mod'=>'le_form',
'type'=>'css',
'link'=>'/pub/css/le_form.css'];
$st_cnf[] = [
'mod'=>'ckeditor5',
'type'=>'js',
'link'=>'https://cdn.ckeditor.com/ckeditor5/27.1.0/classic/ckeditor.js'];
$st_cnf[] = [
'mod'=>'codemirror',
'type'=>'css',
'link'=>'https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.48.4/codemirror.min.css'];
$st_cnf[] = [
'mod'=>'tui-editor',
'type'=>'css',
'link'=>'https://uicdn.toast.com/editor/latest/toastui-editor.min.css'];
$st_cnf[] = [
'mod'=>'tui-editor',
'type'=>'js',
'link'=>'https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js'
//'link'=>'/pub/js/tui-editor.js'
];
$st_cnf[] = [
'mod'=>'jquery',
'type'=>'js',
'link'=>'https://code.jquery.com/jquery-3.6.0.slim.min.js'];
$st_dep['tui-editor']=['codemirror','oth'];

26
copyrights.txt Normal file
View File

@@ -0,0 +1,26 @@
This project based on many open source projects.
#######################
## CSS, Images, Icons #
#######################
1. normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css
2. Google Material Icons
3. Hamburger menu https://atuin.ru/blog/gamburger-ikonki-s-animirovannymi-perexodami/
#######################
# JS Scipts and libs #
#######################
1. JQuery v3.6 https://jquery.com/
2. CkEditor5 https://ckeditor.com/ckeditor-5/download/
3. ToastUI https://ui.toast.com/tui-editor
########################
# PHP Scripts and Libs #
########################
1. PHP Spreadsheet

44
init.php Normal file
View File

@@ -0,0 +1,44 @@
<?php
/********************************************
* LE Framework v0.1 | 18.04.2021 *
* Lite Elephant (PHP) Framework *
* Elizavet , Ural State, Russia *
* Thanks to many open source projects *
* read copyrights.txt file *
* ---------------------------------------- *
* by Pavel Belyaev | pavelbbb@gmail.com *
* Tech-Research.Ru *
*********************************************/
if (!defined("APPDIR") || !is_dir(APPDIR)) exit ("APPDIR not defined");
define("DS",DIRECTORY_SEPARATOR); //directory separator (/ or \)
define("SYSDIR", __DIR__.DS); // system dir
define("I", SYSDIR."LE".DS); //include sys files
require I."deprecated.php";
require I."core.php";
LE::DEF("VER","0.1.0");
LE::DEF("CLI"); //console mode 0
LE::DEF('BR',(CLI?PHP_EOL:'<br/>')); //перенос строк
LE::DEF('ISWEB',(!CLI)); //web mode 1
LE::DEF('WEBDIR',APPDIR."web".DS);
define('CLSDIR', SYSDIR.'CLASSES'.DS); //class sys
define('CORE_CLSDIR', CLSDIR.'core'.DS); //core class sys
define('CLSDIR2', APPDIR.'CLASSES'.DS); //class app
require I."sys_conf.php";
include I."sys_autoload.php";
include I."db_init.php"; //mysql
if (ISWEB):
include I."session.php";
LE::$TPL = new LE_TPL; //шаблонизатор
include I."load_mod.php"; //load module
LE::$TPL->display();
exit();
else:
LE::DEF('SDOM', 'localhost');
endif;