meraproject/module/core/site/theme/model.php

714 lines
28 KiB
PHP
Raw Normal View History

<?
namespace core\site;
use blog\Blog;
use common\moderation\domain\Group as ModerationDomainsGroup;
use common\template\Email;
use core\site\theme\structure\eThemeOption;
use kbase\Kbase;
use ModuleBZ\YandexTurbo;
use ms\ms\structure\msModuleTable;
use core\site\theme\structure\eThemes;
use common\image;
use shop\Cashback;
use shop\cashback\Profile as CashbackProfile;
use shop\Category;
use shop\Item;
use shop\Shop;
use themes\ABOKSchool;
use themes\AcademyTheme;
use themes\ActiveUser;
use themes\AlexShadow;
use themes\Alsor;
use themes\ApiClub;
use themes\AzbukaPeril;
use themes\BBFlowers;
use themes\BeautyMarket;
use themes\BurPar;
use themes\ChangeBlog;
use themes\CircleOfLight;
use themes\Cosmo;
use themes\Covid2019;
use themes\DailyBouquet;
use themes\ElectroSiemens;
use themes\Fixgarden;
use themes\Fixgarden_Design;
use themes\Fixgarden_Ecofir;
use themes\Fixgarden_Gazon;
use themes\Fixgarden_Snow;
use themes\Fixgarden_Water;
use themes\FixgardenCRM;
use themes\FlavoMarket;
use themes\Fnews;
use themes\GeekApp;
use themes\Gulmarket;
use themes\Headway;
use themes\Iqpro;
use themes\JivayaSreda;
use themes\JullifloCRM;
use themes\Gvozdikov;
use themes\Kaboyashi;
use themes\kadigarden;
use themes\KnowledgeBase;
use themes\ManyQuests;
use themes\Merakom;
use themes\MerakomBase;
use themes\Merakomis;
use themes\MerakomRu;
use themes\MesoIgli;
use themes\MetalBase;
use themes\MiniCourse;
use themes\MonteLuxe;
use themes\Mstome;
use themes\Petraline;
use themes\Photofix;
use themes\Roots;
use themes\RootsCRM;
use themes\RotarBlog;
use themes\Sarkko;
use themes\Sense;
use themes\SenseFlowers;
use themes\Solist;
use themes\StepCourse;
use themes\StrategyForum;
use themes\StrategyFound;
use themes\StreetGuru;
use themes\TaskCRM;
use themes\Test;
use themes\Arzumanov;
use themes\Bergamot;
use themes\Bouquet;
use themes\Compare;
use themes\Dsek;
use themes\Fixgarden_Fir;
use themes\Julliflo;
use themes\KPTracking;
use themes\Lashbelong;
use themes\Lander;
use themes\InstaPlanner;
use themes\Modulebz;
use themes\MyBooks;
use themes\Paporotnik;
use themes\Opr;
use themes\Projectman;
use themes\RootsSchool;
use themes\Sova;
use themes\EventHunt;
use themes\ThePirog;
use themes\Timer;
use themes\Tomsky;
use themes\TurboConstructor;
use themes\Varus;
use themes\VedRating;
use themes\VedStat;
use themes\VHL;
use themes\ZlatoMebel;
class Theme {
static $START_INIT;
static $name = '';
static $themeUrl = '';
static $self = null;
static $options = [];
static $data = null;
static $owner_id = null;
static $modules = [];
static $module_prefix = '';
static $google_captcha_secret = '';
static $SMTP_LOGIN = null;
static $SMTP_PASSWORD = null;
static $SMTP_HOST = null;
// ПЕРЕМЕННЫЕ ДЛЯ ТЕМ, ДЛЯ АБСТРАКТНЫХ ФУНКЦИЙ
const PAGE_NEWS_PASS = 'new_pass';
const PAGE_PROFILE = 'profile';
const PAGE_REMIND = 'remind';
public static $_SHOP;
public static $_EMAIL_REG = 'email_reg';
public static $_EMAIL_REMIND_PASSWORD = 'email_remind_password';
/** @var Shop */
public static $SHOP;
/** @var Email */
public static $EMAIL_REG;
/** @var Email */
public static $EMAIL_REMIND_PASSWORD;
static function getNameForTurboShop():string{return '';}
static function getCompanyForTurboShop():string{return '';}
static function getItemLinkForTurboShop($v):string{return '';}
static function getItemLinkForMerchant($v):string{return '';}
static function getNameForGoogleMerchant():string{return '';}
static function getDescriptionForGoogleMerchant():string{return '';}
static function afterRegProfile($profile_id,$data){}
static function onComplaint($id){}
static function getTinyMCEImageUploadUrl():string{return '';}
static function getTinyMCEApiKey():string{return '';}
static function getTurboShop($options = []){
$s = static::$SHOP->_getCatalogStructure();
$categories = [];
foreach ($s['base'] as $cat_id=>$v){
$categories[] = '<category id="'.$cat_id.'">'.Category::getName($v).'</category>';
}
/*
<delivery-options>
<option cost="200" days="1"/>
</delivery-options>
/**/
$offers = [];
$info = static::$SHOP->_getItems();
$cats_items = static::$SHOP->_getItemCategories(array_keys($info['items']));
foreach ($info['items'] as $v){
$img = \Site::sectionUrl( substr( static::$SHOP->_autologo($v[Image::$URL]), 1), true);
$id = $v[Item::$ID];
$cat_id = $cats_items[$id][0];
if(!$s['base'][$cat_id]) continue;
$descr = ( $c = $v[Item::$TEXT] ) ? $c :'Нет описания';
$offers[] = '
<offer id="'.$id.'">
<name>'.Item::getName($v).'</name>
<url>'.\Site::sectionUrl(substr(static::getItemLinkForTurboShop($v),1),true).'</url>
<price>'.$v['price'].'</price>
<currencyId>RUR</currencyId>
<categoryId>'.$cat_id.'</categoryId>
<delivery>true</delivery>
<picture>'.$img.'</picture>
'.($descr?'<description>
<![CDATA[
'.$descr.'
]]>
</description>':'').'
</offer>
';
}
$res = '<?xml version="1.0" encoding="UTF-8"?>'."\n".
'<yml_catalog date="'.date('Y-m-d').'T'.date('H:i:s').'+03:00">
<shop>
<name>'.static::getNameForTurboShop().'</name>
<company>'.static::getCompanyForTurboShop().'</company>
<url>'.\Site::sectionUrl('',true).'</url>
<currencies>
<currency id="RUR" rate="1"/>
</currencies>
<categories>'.implode($categories).'</categories>
<!--
<delivery-options></delivery-options>
-->
<offers>'.implode($offers).'</offers>
<gifts>
<!-- подарки не из прайс‑листа -->
</gifts>
<promos>
<!-- промоакции -->
</promos>
</shop>
</yml_catalog>';
return $res;
}
static function echoMerchant(){
$info = static::$SHOP->_getItems();
$res = [];
$isUpdate = boolval($_GET['update']);
if ($isUpdate) {
$res []= "id\tavailability\tprice";
} else {
$res []= "id\ttitle\tdescription\tlink\timage_link\tavailability\tcondition\tprice";
}
$prepare = function($t){
return '"'.strip_tags(str_replace(array("<br/>",","),array(" ","."),$t)).'"';
};
foreach ($info['items'] as $v){
$code = "item".$v[Item::$ID];
if($isUpdate){
$res[] = implode("\t",[
$code,
"in stock",
$v['price'].' RUB'
]);
} else {
$img = Image::imageResize($v[Image::$URL],1000,0,95);
$res[] = implode("\t",[
$code,
$prepare( Item::getName($v) ),
$prepare( $v[Item::$TEXT]?:'Описание отсутствует' ),
\Site::sectionUrl(substr(static::getItemLinkForMerchant($v),1),true),
\Site::sectionUrl(substr($img,1),true),
"in stock",
"new",
$v['price'].' RUB'
]);
}
}
echo implode("\n",$res);
}
static function echoMerchantXML(){
$info = static::$SHOP->_getItems();
$res = [];
$items = '';
$title = static::getNameForGoogleMerchant();
$structure = static::$SHOP->_getCatalogStructure();
foreach ($info['items'] as $v){
$code = "item".$v[Item::$ID];
$img = Image::imageResize($v[Image::$URL],1000,0,95);
$link = static::getItemLinkForMerchant($v);
$url = explode("/",$link);
array_pop($url);
array_pop($url);
array_shift($url);
$cat = static::$SHOP->_getCategoryByURL($url);
$path = static::$SHOP->_getCategoryPath($cat[Category::$ID]);
$crumbs = ['Главная'];
foreach ($path as $part){
$crumbs[] = Category::getName($structure['base'][$part]);
}
$items.='
<item>
<g:id>item'.$v[Item::$ID].'</g:id>
<g:title>'.Item::getName($v).'</g:title>
<g:description>'.strip_tags($v[Item::$TEXT]).'</g:description>
<g:link>'.\Site::sectionUrl(substr($link,1),true).'</g:link>
<g:image_link>'.\Site::sectionUrl(substr($img,1),true).'</g:image_link>
<g:condition>new</g:condition>
<g:availability>in stock</g:availability>
<g:price>'.$v['price'].' RUB'.'</g:price>
<g:google_product_category>2899</g:google_product_category>
<g:product_type>'.implode("&gt;",$crumbs).'</g:product_type>
<g:brand>'.$title.'</g:brand>
<g:custom_label_0>Анна</g:custom_label_0>
</item>
';
}
$res = '<?xml version="1.0"?>
<rss version="2.0" xmlns:g="http://base.google.com/ns/1.0">
<channel>
<title>'.$title.'</title>
<link>'.\Site::$domen.'</link>
<description>'.static::getDescriptionForGoogleMerchant().'</description>
'.$items.'
</channel>
</rss>';
//*
header("Content-Type: text/xml");
//header("Expires: Thu, 19 Feb 1998 13:24:18 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Cache-Control: post-check=0,pre-check=0");
header("Cache-Control: max-age=0");
header("Pragma: no-cache");
echo $res;
/**/
}
static function sitemap():array{return [];}
static function getSitemap(){
$a = static::sitemap();
$res = '';
foreach ($a as $v){
$imgs = '';
if($v['images']){
foreach ($v['images'] as $img){
$img = trim($img);
if($img) {
$imgs .= '<image:image><image:loc>' . $img . '</image:loc></image:image>';
}
}
}
$res .= '<url>'
.(($c = $v['link'])? '<loc>'.$c.'</loc>' :'')
.(($c = $v['date'])? '<lastmod>'.$c.'</lastmod>' :'')
.(($c = $v['change'])? '<changefreq>'.$c.'</changefreq>' :'')
.(($c = $v['prior'])? '<priority>'.$c.'</priority>' :'')
.$imgs
.'</url>';
}
return '<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">'.$res.'</urlset>';
}
static function getProfileAuthHash($acc){return null;}
static function getCashbackPercent($order_id):float{
$res = 0;
if(static::$SHOP){
$group_id = intval(static::$SHOP->data_for_theme[Shop::$CASHBACK_GROUP]);
if($group_id and IF_PROFILE){
$cashback = CashbackProfile::get(PID,$group_id);
if($cashback) {
$res = cfloatval($cashback[Cashback::$PERCENT])/100;
}
} else {
$res = floatval(static::$SHOP->data_for_theme[Shop::$CASHBACK_VALUE]) / 100;
}
}
return $res;
}
static function getLastReactJSPath(){
$path = \Core::$FOLDER.( $res = \Site::$themeAbsPath.'js/react/' );
$handle = opendir($path);
$LAST_JS = 0;
$folders = [];
if ($handle){
while(false !== ($file = readdir($handle))) {
if(is_numeric($file)) {
$int = intval($file);
$LAST_JS = max( $LAST_JS, $int );
$folders[] = $int;
}
}
}
foreach ($folders as $v){
$p = $path.$v.'/';
if($v!=$LAST_JS) {
$handle = opendir($p);
while(false !== ($file = readdir($handle))) {
$f = $p.$file;
if(is_file($f)) {
unlink($f);
}
}
rmdir($p);
}
}
return $res.$LAST_JS.'/';
}
static function getProfileHash($key,$profile) {return md5($key.SALT.$profile[\Profile::$PASSWORD].SALT.static::$themeUrl); }
static function checkRemind($profile_id,$key,$hash){
$res = null;
$profile_id = intval($profile_id);
$profile = \Profile::getByID($profile_id);
$key = intval($key);
$hash2 = static::getProfileHash($key,$profile);
if($key + 60*60*24 < time()){
$res = 'В целях безопасности время на смену пароля ограничено и действие подтверждающих данных уже истекло. Начните восстановление пароля заново.';
} else if(strcmp($hash,$hash2)!=0) {
$res = 'Неверные подтверждающие коды.';
}
return $res;
}
static function getRemindLink($profile){
$key = time();
$id = $profile[\Profile::$ID];
$hash = static::getProfileHash($key,$profile);
return \Site::sectionUrl(static::PAGE_PROFILE.'/'.static::PAGE_NEWS_PASS.'/'.$id.'/'.$key.'/'.$hash.'/', true);
}
static function checkGoogleCaptcha($google_token){
$res = ['e'=>0,'m'=>''];
if($_SERVER['HTTP_HOST']=='julliflo.in') return $res;
if(static::$google_captcha_secret and !$google_token) {
$res = ['e'=>1,'m'=>'Не прислан гугл токен капчи'];
}
if(static::$google_captcha_secret and $google_token){
if ($curl = curl_init()) {
$url = 'https://www.google.com/recaptcha/api/siteverify';
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, [
'secret' => static::$google_captcha_secret,
'response' => $google_token,
]);
$out = curl_exec($curl);
curl_close($curl);
$r = json_decode($out, true);
if ($r['success']) {
if ($r['score'] < 0.7) {
sendEasyMail('Google Captcha',
'no-reply@'.$_SERVER['HTTP_HOST'],
'Виктор',
'79175032799@ya.ru',
'UTF-8',
'UTF-8',
'Google Captcha Error',
json_encode($_GET).'<br>'.json_encode($_POST).'<br>'.json_encode($_REQUEST).'<br>'.json_encode($r),'html');
$res['e'] = 1;
$res['m'] = 'Не пройдена гугл капча';
$f = fopen(dirname(__FILE__).'/captcha.txt','a+');
fwrite($f,date('Y.m.d H:i:s')."\n".json_encode($_GET)."\n".json_encode($_POST)."\n".json_encode($_SERVER)."\n".json_encode($r)."\n\n");
fclose($f);
}
} else {
$res['e'] = 1;
$res['m'] = 'Не пройдена гугл капча';
}
$res['google'] = $r;
}
}
return $res;
}
static function getEmailWrap():string { return ''; }
static function sendEmailRemind($profile){
Email::sendRemindPassword(
static::$EMAIL_REMIND_PASSWORD->id_for_theme,
$profile,
static::getRemindLink($profile),
static::getEmailWrap(),
$profile[\Profile::$LOGIN],
$profile[\Profile::$NAME]
);
}
// Получение различных списков для формы настроек
static function getEmailsForForm(){
$r = Email::select([
\Query::WHERE => new \Where(\Where::_operator(Email::$ACCOUNT,'=',UID))
],false);
$emails = [];
while($l = \DB::fetch($r)){
$emails[ $l[Email::$TYPE] ][ $l[Email::$ID] ] = Email::getName($l);
}
return $emails;
}
static function getBlogsForForm(){
return Blog::getNameList([
\Query::WHERE => new \Where(\Where::_operator(Blog::$ACCOUNT,'=',UID))
]);
}
static function getKbaseForForm(){
return Kbase::getNameList([
\Query::WHERE => new \Where(\Where::_operator(Kbase::$ACCOUNT,'=',UID))
]);
}
static function getDomainsGroupForForm(){
return ModerationDomainsGroup::getNameList([
\Query::WHERE => new \Where(\Where::_operator(ModerationDomainsGroup::$ACCOUNT,'=',UID))
]);
}
static function prepare() {
$data = static::$data;
$a = static::getOptions();
foreach ($a as $k=>$v){
$x = strtoupper($k);
if($v[eThemeOption::CONTROLLER]) {
if( $id = intval( $data[$k] ) ) {
switch ($v[eThemeOption::CONTROLLER]){
case 'common\image':
if($data[$k]) static::$$x = Image::getByID($data[$k]);
break;
default:
static::$$x = new $v[eThemeOption::CONTROLLER];
static::$$x->id_for_theme = $id;
static::$$x->owner_id = static::$owner_id;
static::$$x->data_for_theme = $v[eThemeOption::CONTROLLER]::getByID(intval($id));
}
}
} else {
static::$$x = $data[$k];
}
}
}
static function getForm(){return [];}
static function getOptions():array{return [];}
static function getSystemLangValues():array{return [];}
function __construct($data=[]) {
static::$data = $data;
//static::prepare();
}
static function getYML():string{return '';}
static function getTurbo():YandexTurbo{ return new YandexTurbo(); }
static function sendEmailRegistration($id){}
static function favicon($img){
$path = \Site::$themeAbsPath.'favicon'.$img[Image::$ID].".ico";
$full_path = \Core::$FOLDER.$path;
if(!file_exists($full_path) and $img) {
$ico_lib = new \PHP_ICO( \Core::$FOLDER.$img[Image::$ORIGINAL], array(array(16, 16), array(24, 24), array(32, 32), array(48, 48)));
$r = $ico_lib->save_ico($full_path);
}
return $path;
}
static function init($theme_id,$data=[],$owner_id = 0):Theme{
static::$START_INIT = microtime(true);
static::$data = $data;
static::$owner_id = intval($owner_id);
switch ($theme_id) {
case eThemes::KADIGARDEN: $res = new Kadigarden($data); break;
case eThemes::TEST: $res = new Test($data); break;
case eThemes::LASHBELONG: $res = new Lashbelong($data); break;
case eThemes::KBASE: $res = new KnowledgeBase($data); break;
case eThemes::ACADEMY: $res = new AcademyTheme($data); break;
case eThemes::FIXGARDEN: $res = new Fixgarden($data); break;
case eThemes::LANDING: $res = new Lander($data); break;
case eThemes::INSTAPLANNER: $res = new InstaPlanner($data); break;
case eThemes::PAPOROTNIK: $res = new Paporotnik($data); break;
case eThemes::OPR: $res = new Opr($data); break;
case eThemes::DSEK: $res = new Dsek($data); break;
case eThemes::MODULEBZ: $res = new Modulebz($data); break;
case eThemes::COMPARE: $res = new Compare($data); break;
case eThemes::SOVA: $res = new Sova($data); break;
case eThemes::BERGAMOT: $res = new Bergamot($data); break;
case eThemes::ROOTS_SCHOOL: $res = new RootsSchool($data); break;
case eThemes::KPTRACKING: $res = new KPTracking($data); break;
case eThemes::MYBOOKS: $res = new MyBooks($data); break;
case eThemes::EVENTHUNT: $res = new EventHunt($data); break;
case eThemes::BOUQUET: $res = new Bouquet($data); break;
case eThemes::PROJECTMAN: $res = new Projectman($data); break;
case eThemes::JULLIFLO: $res = new Julliflo($data); break;
case eThemes::ARZUANOV: $res = new Arzumanov($data); break;
case eThemes::FIXGARDEN_FIR: $res = new Fixgarden_Fir($data); break;
case eThemes::MSTOME: $res = new Mstome($data); break;
case eThemes::VARUS: $res = new Varus($data); break;
case eThemes::ROTARBLOG: $res = new RotarBlog($data); break;
case eThemes::CIRCLEOFLIGHT: $res = new CircleOfLight($data); break;
case eThemes::APICLUB: $res = new ApiClub($data); break;
case eThemes::JULLIFLOCRM: $res = new JullifloCRM($data); break;
case eThemes::MERAKOM: $res = new Merakom($data); break;
case eThemes::THEPIROG: $res = new ThePirog($data); break;
case eThemes::GVOZDIKOV: $res = new Gvozdikov($data); break;
case eThemes::STRATEGYFOUND: $res = new StrategyFound($data); break;
case eThemes::TIMER: $res = new Timer($data); break;
case eThemes::STRATEGYFORUM: $res = new StrategyForum($data); break;
case eThemes::TASKCRM: $res = new TaskCRM($data); break;
case eThemes::DAILYBOUQUET: $res = new DailyBouquet($data); break;
case eThemes::VEDSTAT: $res = new VedStat($data); break;
case eThemes::COVID2019: $res = new Covid2019($data); break;
case eThemes::ROOTS: $res = new Roots($data); break;
case eThemes::ROOTS_CRM: $res = new RootsCRM($data); break;
case eThemes::COSMO: $res = new Cosmo($data); break;
case eThemes::CHANGE_BLOG: $res = new ChangeBlog($data); break;
case eThemes::BBFLOWERS: $res = new BBFlowers($data); break;
case eThemes::ABOK_SCHOOL: $res = new ABOKSchool($data); break;
case eThemes::ACTIVE_USER: $res = new ActiveUser($data); break;
case eThemes::STEPCOURSE: $res = new StepCourse($data); break;
case eThemes::JIVAYA_SREDA: $res = new JivayaSreda($data); break;
case eThemes::KABOYASHI: $res = new Kaboyashi($data); break;
case eThemes::MERAKOM_RU: $res = new MerakomRu($data); break;
case eThemes::PETRALINE: $res = new Petraline($data); break;
case eThemes::GULMARKET: $res = new Gulmarket($data); break;
case eThemes::SOLIST: $res = new Solist($data); break;
case eThemes::BEAUTY_MARKET: $res = new BeautyMarket($data); break;
case eThemes::AZBUKA_PERIL : $res = new AzbukaPeril($data); break;
case eThemes::MONTELUXE : $res = new MonteLuxe($data); break;
case eThemes::STREETGURU : $res = new StreetGuru($data); break;
case eThemes::MINICOURSE : $res = new MiniCourse($data); break;
case eThemes::FIXGARDENCRM : $res = new FixgardenCRM($data); break;
case eThemes::HEADWAY : $res = new Headway($data); break;
case eThemes::ELECTROSIEMENS : $res = new ElectroSiemens($data); break;
case eThemes::SENSE_FLOWERS : $res = new SenseFlowers($data); break;
case eThemes::ZLATOMEBEL : $res = new ZlatoMebel($data); break;
case eThemes::VHL : $res = new VHL($data); break;
case eThemes::ALEX_SHADOW : $res = new AlexShadow($data); break;
case eThemes::METAL_BASE : $res = new MetalBase($data); break;
case eThemes::MANY_QUESTS : $res = new ManyQuests($data); break;
case eThemes::TOMSKY : $res = new Tomsky($data); break;
case eThemes::ALSOR : $res = new Alsor($data); break;
case eThemes::FNEWS : $res = new Fnews($data); break;
case eThemes::MERAKOM_BASE : $res = new MerakomBase($data); break;
case eThemes::MERAKOM_IS : $res = new Merakomis($data); break;
case eThemes::FLAVOMARKET : $res = new FlavoMarket($data); break;
case eThemes::MESOIGLI : $res = new MesoIgli($data); break;
case eThemes::VEDRATING : $res = new VedRating($data); break;
case eThemes::FIXGARDEN_GAZON: $res = new Fixgarden_Gazon($data); break;
case eThemes::PHOTOFIX : $res = new Photofix($data); break;
case eThemes::FIXGARDEN_ECOFIR : $res = new Fixgarden_Ecofir($data); break;
case eThemes::FIXGARDEN_SNOW : $res = new Fixgarden_Snow($data); break;
case eThemes::BURPAR : $res = new BurPar($data); break;
case eThemes::GEEKAPP : $res = new GeekApp($data); break;
case eThemes::SARKKO : $res = new Sarkko($data); break;
case eThemes::FIXGARDEN_DESIGN :$res = new Fixgarden_Design($data); break;
case eThemes::FIXGARDEN_WATER :$res = new Fixgarden_Water($data); break;
case eThemes::IQPRO :$res = new Iqpro($data); break;
default: $res = new Theme($data);
}
static::$self = $res;
static::$options = static::getOptions();
return static::$self;
}
static function install(){
foreach (self::$modules as $v){
/** @var msModuleTable $class */
$class = static::$module_prefix.'\\'.$v;
$class::install();
}
static::migrate();
}
static function migrate(){
foreach (static::$modules as $v){
/** @var msModuleTable $class */
$class = static::$module_prefix.'\\'.$v;
$class::createTable();
$class::checkColumns(true);
$class::installLangValues($class::getSystemLangValues(),['isUpdate'=>true]);
$class::installUniques();
}
$s = static::getSystemLangValues();
\Module::installLangValues(static::getSystemLangValues(),['isUpdate'=>true]);
}
}