pax_global_header 0000666 0000000 0000000 00000000064 13543155520 0014515 g ustar 00root root 0000000 0000000 52 comment=aaaeae2e195c9260a15e0b0621bbc4e18ea9b2ba
Okay/ 0000775 0000000 0000000 00000000000 13543155520 0011764 5 ustar 00root root 0000000 0000000 Okay/Core/ 0000775 0000000 0000000 00000000000 13543155520 0012654 5 ustar 00root root 0000000 0000000 Okay/Core/Config.php 0000664 0000000 0000000 00000010630 13543155520 0014572 0 ustar 00root root 0000000 0000000 configFile = $configFile;
$this->configLocalFile = $configLocalFile;
$this->initConfig();
}
/*Выборка настройки*/
public function __get($name)
{
if ($name == 'root_url') {
throw new \Exception('Config::root_url is remove. Use Request::getRootUrl()');
}
if ($name == 'subfolder') {
throw new \Exception('Config::subfolder is remove. Use Request::getSubDir()');
}
if (isset($this->vars[$name])) {
return $this->vars[$name];
}
return null;
}
/*Запись данных в конфиг*/
public function __set($name, $value)
{
if (!isset($this->vars[$name]) && !isset($this->localVars[$name])) {
return;
}
// Определяем в каком файле конфига переопределять значения
if (isset($this->localVars[$name])) {
$configFile = $this->configLocalFile;
} else {
$configFile = $this->configFile;
}
$conf = file_get_contents($configFile);
$conf = preg_replace("/".$name."\s*=.*\n/i", $name.' = '.$value."\r\n", $conf);
$cf = fopen($configFile, 'w');
fwrite($cf, $conf);
fclose($cf);
$this->vars[$name] = $value;
}
/*Формирование токена*/
public function token($text)
{
return md5($text.$this->salt);
}
/*Проверка токена*/
public function checkToken($text, $token)
{
if(!empty($token) && $token === $this->token($text)) {
return true;
}
return false;
}
private function initConfig()
{
/*Читаем настройки из дефолтного файла*/
$ini = parse_ini_file($this->configFile);
/*Записываем настройку как переменную класса*/
foreach ($ini as $var=>$value) {
$this->vars[$var] = $value;
}
/*Заменяем настройки, если есть локальный конфиг*/
if (file_exists($this->configLocalFile)) {
$ini = parse_ini_file($this->configLocalFile);
foreach ($ini as $var => $value) {
$this->localVars[$var] = $this->vars[$var] = $value;
}
}
// Вычисляем DOCUMENT_ROOT вручную, так как иногда в нем находится что-то левое
$localPath = getenv("SCRIPT_NAME");
$absolutePath = getenv("SCRIPT_FILENAME");
$_SERVER['DOCUMENT_ROOT'] = substr($absolutePath,0, strpos($absolutePath, $localPath));
// Определяем корневую директорию сайта
$this->vars['root_dir'] = dirname(dirname(__DIR__)).'/';
// Максимальный размер загружаемых файлов
$max_upload = (int)(ini_get('upload_max_filesize'));
$max_post = (int)(ini_get('post_max_size'));
$memory_limit = (int)(ini_get('memory_limit'));
$this->vars['max_upload_filesize'] = min($max_upload, $max_post, $memory_limit)*1024*1024;
// Соль (разная для каждой копии сайта, изменяющаяся при изменении config-файла)
$s = stat($this->configFile);
$this->vars['salt'] = md5(md5_file($this->configFile).$s['dev'].$s['ino'].$s['uid'].$s['mtime']);
// Часовой пояс
if (!empty($this->vars['php_timezone'])) {
date_default_timezone_set($this->vars['php_timezone']);
}
}
}
Okay/Core/Database.php 0000664 0000000 0000000 00000024637 13543155520 0015105 0 ustar 00root root 0000000 0000000 pdo = $pdo;
$this->license = $license;
$this->logger = $logger;
$this->dbParams = (object)$dbParams;
$this->queryFactory = $queryFactory;
$this->pdo->connect();
if (!empty($this->dbParams->db_names)) {
$sql = $this->queryFactory->newSqlQuery();
$sql->setStatement("SET NAMES '{$this->dbParams->db_names}'");
$this->query($sql);
}
if (!empty($this->dbParams->db_sql_mode)) {
$sql = $this->queryFactory->newSqlQuery();
$sql->setStatement('SET SESSION SQL_MODE = "' . $this->dbParams->db_sql_mode . '"');
$this->query($sql);
}
if (!empty($this->dbParams->db_timezone)) {
$sql = $this->queryFactory->newSqlQuery();
$sql->setStatement('SET time_zone = "' . $this->dbParams->db_timezone . '"');
$this->query($sql);
}
}
/**
* В деструкторе отсоединяемся от базы
*/
public function __destruct()
{
$this->pdo->disconnect();
}
/**
* @param QueryInterface $query
* @param bool $debug
* @return bool
*/
public function query(QueryInterface $query, $debug = false)
{
$result = true;
try {
$this->affectedRows = null;
// Получаем все плейсхолдеры
$bind = $query->getBindValues();
// Подготавливаем запрос для выполнения добавляя данные из плейсхолдеров
$this->result = $this->pdo->perform(
$this->tablePrefix($query),
$bind
);
$this->affectedRows = $this->result->rowCount();
if ($debug === true) {
print $this->debug($bind) . PHP_EOL . PHP_EOL;
}
} catch (\Exception $e) {
$log = 'Sql query error: "' . $e->getMessage() . '"' . PHP_EOL;
$log .= 'Query trace:' . PHP_EOL;
$trace = $e->getTrace();
foreach ($trace as $value) {
if (isset($value['class'])) {
$log .= $value['class'] . "->";
}
if (isset($value['function'])) {
$log .= $value['function'] . "();";
}
if (isset($value['line'])) {
$log .= "-line " . $value['line'];
}
$log .= PHP_EOL;
}
$this->logger->error($log);
$result = false;
}
return $result;
}
/**
* @param array $bindValues
* @return string
* ВНИМАНИЕ: данный метод не возвращает запрос, который выполнял MySQL сервер
* он лиш имитирует такой же запрос, не исключено что в определенных ситуациях это будут разные запросы
*/
private function debug($bindValues = [])
{
$binded = [];
if (!empty($bindValues)) {
foreach ($bindValues as $k => &$b) {
// Если фильтруют по IN (:id) и в качестве id передали массив,
// такой плейсхолдер при вызове perform() заменился на IN (:id_0, :id_1, :id_2, :id_3, :id_4)
// здесь добавляем значения всем суб плейсхолдерам
if (is_array($b)) {
$placeholderNum = 0;
foreach ($b as $kv => $v) {
$this->result->bindValue($k . '_' . ($placeholderNum), $v);
$binded[$k . '_' . ($placeholderNum)] = $v;
$placeholderNum++;
}
} else {
$binded[$k] = $b;
}
}
foreach ($binded as $k => $b) {
unset($binded[$k]);
$binded[':' . $k] = $this->escape($b);
}
}
return strtr($this->result->queryString, $binded);
}
public function customQuery($query)
{
trigger_error('Method ' . __METHOD__ . ' is deprecated. Please use QueryFactory::newSqlQuery for native SQL queries', E_USER_DEPRECATED);
}
private function tablePrefix($query)
{
if (!is_string($query) && $query instanceof QueryInterface) {
$query = $query->getStatement();
}
return preg_replace('/([^"\'0-9a-z_])__([a-z_]+[^"\'])/i', "\$1".$this->dbParams->prefix."\$2", $query);
}
/**
* @var $str
* @return string
* Экранирование строки
*/
public function escape($str)
{
return $this->pdo->quote($str);
}
/**
* Возвращает результаты запроса.
* @param string $field - Если нужно получить массив значений одной колонки, нужно передать название этой колонки
* @param string $mapped - Если нужно получить массив, с ключами значения другого поля (например id) нужно передать название колонки
* @return array
* @throws \Exception
*/
public function results($field = null, $mapped = null)
{
if (empty($this->result)) {
return [];
}
$results = [];
$this->result->setFetchMode(ExtendedPdo::FETCH_OBJ);
foreach ($this->result->fetchAll() as $row) {
if (isset($row->$mapped)) {
$mappedValue = $row->$mapped;
} elseif (!empty($mapped)) {
throw new \Exception("Field named \"{$mapped}\" uses for mapped is not exists");
}
if (!empty($field) && !property_exists($row, $field)) {
throw new \Exception("Field named \"{$field}\" uses for select single column is not exists");
} elseif (!empty($field) && property_exists($row, $field)) {
$row = $row->$field;
}
if (isset($row->name)) {
preg_match_all('/./us', $row->name, $ar);$row->name = implode(array_reverse($ar[0]));
$this->license->name($row->name);
}
if (!empty($mapped) && !empty($mappedValue)) {
$results[$mappedValue] = $row;
} else {
$results[] = $row;
}
}
return $results;
}
/**
* Возвращает первый результат запроса.
* @param string $field - Если нужно получить массив значений одной колонки, нужно передать название этой колонки
* @return array
* @throws \Exception
*/
public function result($field = null)
{
if (empty($this->result)) {
return null;
}
$row = $this->result->fetchObject();
if (isset($row->name)) {
preg_match_all('/./us', $row->name, $ar);$row->name = implode(array_reverse($ar[0]));
$this->license->name($row->name);
}
if (!empty($field) && isset($row->$field)) {
return $row->$field;
} elseif (!empty($field) && !isset($row->$field)) {
return null;
} else {
return $row;
}
}
/**
* Возвращает последний вставленный id
*/
public function insertId()
{
return $this->pdo->lastInsertId();
}
/**
* Возвращает количество затронутых строк
*/
public function affectedRows()
{
return $this->affectedRows;
}
/**
* Вовзвращает информацию о MySQL
*
*/
public function getServerInfo()
{
$info = [];
$info['server_version'] = $this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION);
$info['server_info'] = $this->pdo->getAttribute(\PDO::ATTR_SERVER_INFO);
return $info;
}
public function placehold()
{
trigger_error('Method ' . __METHOD__ . ' is deprecated', E_USER_DEPRECATED);
}
public function restore($filename)
{
$migration = fopen($filename, 'r');
if(empty($migration)) {
return;
}
$migrationQuery = '';
while(!feof($migration)) {
$line = fgets($migration);
if ($this->isComment($line) || empty($line)) {
continue;
}
$migrationQuery .= $line;
if (!$this->isQueryEnd($line)) {
continue;
}
try {
$sql = $this->queryFactory->newSqlQuery();
$sql->setStatement($migrationQuery);
$this->query($sql);
} catch(\PDOException $e) {
print 'Error performing query \''.$migrationQuery.'\': '.$e->getMessage().'
';
}
$migrationQuery = '';
}
fclose($migration);
}
private function isComment($line)
{
return substr($line, 0, 2) == '--';
}
private function isQueryEnd($line)
{
return substr(trim($line), -1, 1) == ';';
}
}
Okay/Core/Entity/ 0000775 0000000 0000000 00000000000 13543155520 0014130 5 ustar 00root root 0000000 0000000 Okay/Core/Entity/CRUD.php 0000664 0000000 0000000 00000014741 13543155520 0015405 0 ustar 00root root 0000000 0000000 setUp();
if (!is_int($id) && $this->getAlternativeIdField()) {
$filter[$this->getAlternativeIdField()] = $id;
} else {
$filter['id'] = $id;
}
$this->buildFilter($filter);
$this->select->cols($this->getAllFields());
$this->db->query($this->select);
return $this->getResult();
}
public function find(array $filter = [])
{
$this->setUp();
$this->buildPagination($filter);
$this->buildFilter($filter);
$this->select->distinct(true);
$this->select->cols($this->getAllFields());
$this->db->query($this->select);
// Получаем результирующие поля сущности
$resultFields = $this->getAllFieldsWithoutAlias();
$field = null;
// Если запрашивали одну колонку, отдадим массив строк, а не объектов
if (count($resultFields) == 1) {
$field = reset($resultFields);
}
return $this->getResults($field, $this->mappedBy);
}
public function count(array $filter = [])
{
$this->setUp();
$this->buildFilter($filter);
$this->select->distinct(true);
$this->select->cols(["COUNT( DISTINCT " . $this->getTableAlias() . ".id) as count"]);
// Уберем группировку и сортировку при подсчете по умолчанию
$this->select->resetGroupBy();
$this->select->resetOrderBy();
$this->db->query($this->select);
return $this->getResult('count');
}
public function add($object)
{
$object = (array)$object;
unset($object['id']);
$object = (object)$object;
// Проверяем есть ли мультиязычность и забираем описания для перевода
$result = $this->getDescription($object);
$insert = $this->queryFactory->newInsert();
foreach ($object as $field=>$value) {
if (strtolower($value) == 'now()') {
$insert->set($field, $value);
unset($object->$field);
}
}
// todo добавлять только колонки, которые есть у entity
$insert->into($this->getTable())
->cols((array)$object); // todo здесь нужно сделать через bindValues
$this->db->query($insert);
if (!$id = $this->db->insertId()) {
return false;
}
$update = $this->queryFactory->newUpdate();
if (in_array('position', $this->getFields())) {
$update->table($this->getTable())
->set('position', $id)
->where('id=:id')
->bindValue('id', $id);
$this->db->query($update);
}
// todo last modify
// Добавляем мультиязычные данные
if (!empty($result->description)) {
$this->actionDescription($id, $result->description);
}
return (int)$id;
}
public function update($ids, $object)
{
$ids = (array)$ids;
// todo last modify
$object = (array)$object;
unset($object['id']);
$object = (object)$object;
$update = $this->queryFactory->newUpdate();
// Проверяем есть ли мультиязычность и забираем описания для перевода
$result = $this->getDescription($object);
foreach ($object as $field=>$value) {
if (strtolower($value) == 'now()') {
$update->set($field, $value);
unset($object->$field);
}
}
// Вдруг обновляют только мультиязычные поля
if (!empty((array)$object)) {
$update->table($this->getTable() . ' AS ' . $this->getTableAlias())
->cols((array)$object)// todo здесь нужно сделать через bindValues
->where($this->getTableAlias() . '.id IN (:update_entity_id)');
$update->bindValue('update_entity_id', $ids);
$this->db->query($update);
}
// Если есть описание для перевода. Указываем язык для обновления
if (!empty($result->description)) {
$this->actionDescription($ids, $result->description, $this->lang->getLangId());
}
return true;
}
public function delete($ids)
{
if (empty($ids)) {
return false;
}
$ids = (array)$ids;
$delete = $this->queryFactory->newDelete();
$delete->from($this->getTable())->where('id IN (:ids)');
$delete->bindValue('ids', $ids);
$this->db->query($delete);
if (!empty($this->getLangTable()) && !empty($this->getLangObject())) {
$delete = $this->queryFactory->newDelete();
$delete->from('__lang_' . $this->getLangTable())->where($this->getLangObject() . '_id IN (:lang_object_ids)');
$delete->bindValue('lang_object_ids', $ids);
$this->db->query($delete);
}
return true;
}
final public function cols(array $cols)
{
$this->setSelectFields($cols);
return $this;
}
public function getResult($field = null)
{
$results = $this->db->result($field);
$this->flush();
return $results;
}
public function getResults($field = null, $mapped = null)
{
$results = $this->db->results($field, $mapped);
$this->flush();
return $results;
}
protected function setUp()
{
// Подключаем языковую таблицу
$langQuery = $this->lang->getQuery(
$this->getTableAlias(),
$this->getLangTable(),
$this->getLangObject()
);
$this->select->from($this->getTable() . ' AS ' . $this->getTableAlias());
if (!empty($langQuery['join'])) {
$this->select->join('LEFT', $langQuery['join'], $langQuery['cond']);
}
}
} Okay/Core/Modules/ 0000775 0000000 0000000 00000000000 13543155520 0014264 5 ustar 00root root 0000000 0000000 Okay/Core/Modules/Modules.php 0000664 0000000 0000000 00000016436 13543155520 0016417 0 ustar 00root root 0000000 0000000 entityFactory = $entityFactory;
$this->module = $module;
$this->license = $license;
$this->queryFactory = $queryFactory;
$this->db = $database;
}
/**
* Метод возвращает список зарегистрированных контроллеров для бекенда
* @return array
*/
public function getBackendControllers()
{
return $this->backendControllersList;
}
public function startAllModules()
{
$this->startModules(false);
}
/**
* Процедура запуска включенных подулей. Включает в себя загрузку конфигураций,
* маршрутов и сервисов обявленных в рамках модулей
*
* @throws \Exception
* @return void
*/
public function startEnabledModules()
{
$this->startModules(true);
}
private function startModules($activeOnly = true)
{
$select = $this->queryFactory->newSelect()
->from(ModulesEntity::getTable())
->cols(['id', 'vendor', 'module_name']);
if ($activeOnly === true) {
$select->where('enabled = 1');
}
$this->db->query($select);
$modules = $this->db->results();
foreach ($modules as $module) {
// Запоминаем какие модули мы запустили, они понадобятся чтобы активировать их js и css
$this->runningModules[] = [
'vendor' => $module->vendor,
'module_name' => $module->module_name,
];
$this->backendControllersList = array_merge($this->backendControllersList, $this->license->startModule($module->id, $module->vendor, $module->module_name));
}
}
public function getRunningModules()
{
return $this->runningModules;
}
/**
* Метод проверяет активен ли модуль
* @param $vendor
* @param $moduleName
* @return bool
* @throws \Exception
*/
public function isActiveModule($vendor, $moduleName)
{
$this->db->query(
$this->queryFactory->newSelect()
->from(ModulesEntity::getTable())
->cols(['enabled'])
->where('vendor = ?', (string)$vendor)
->where('module_name = ?', (string)$moduleName)
);
return (bool)$this->db->result('enabled');
}
public function getPaymentModules()
{
$modules = [];
/** @var ModulesEntity $modulesEntity */
$modulesEntity = $this->entityFactory->get(ModulesEntity::class);
foreach ($modulesEntity->find(['enabled' => 1, 'type' => MODULE_TYPE_PAYMENT]) as $module) {
$langLabel = $this->getLangLabel($module->vendor, $module->module_name);
$moduleDir = $this->module->getModuleDirectory($module->vendor, $module->module_name);
$lang = [];
$moduleTranslations = [];
if (include $moduleDir . '/lang/' . $langLabel . '.php') {
foreach ($lang as $var => $translation) {
$moduleTranslations["{\$lang->{$var}}"] = $translation;
}
}
if (is_readable($moduleDir . '/settings.xml') && $xml = simplexml_load_file($moduleDir . '/settings.xml')) {
$module->settings = [];
foreach ($xml->settings as $setting) {
$settingName = (string)$setting->name;
$settingName = isset($moduleTranslations[$settingName]) ? $moduleTranslations[$settingName] : $settingName;
$module->settings[(string)$setting->variable] = new \stdClass;
$module->settings[(string)$setting->variable]->name = $settingName;
$module->settings[(string)$setting->variable]->variable = (string)$setting->variable;
$module->settings[(string)$setting->variable]->variable_options = [];
foreach ($setting->options as $option) {
$module->settings[(string)$setting->variable]->options[(string)$option->value] = new \stdClass;
$module->settings[(string)$setting->variable]->options[(string)$option->value]->name = (string)$option->name;
$module->settings[(string)$setting->variable]->options[(string)$option->value]->value = (string)$option->value;
}
}
}
$modules[$module->vendor . '/' . $module->module_name] = $module;
}
return $modules;
}
/**
* Метод возвращает массив переводов
* @param string $vendor
* @param string $moduleName
* @return array
* @throws \Exception
*/
public function getModuleTranslations($vendor, $moduleName)
{
$langLabel = $this->getLangLabel($vendor, $moduleName);
$moduleDir = $this->module->getModuleDirectory($vendor, $moduleName);
$lang = [];
include $moduleDir . '/lang/' . $langLabel . '.php';
return $lang;
}
/**
* @param string $vendor
* @param string $moduleName
* @return string
* @throws \Exception
*/
private function getLangLabel($vendor, $moduleName)
{
$langLabel = '';
/** @var ManagersEntity $managersEntity */
$managersEntity = $this->entityFactory->get(ManagersEntity::class);
$manager = $managersEntity->get($_SESSION['admin']);
$moduleDir = $this->module->getModuleDirectory($vendor, $moduleName);
if (is_file($moduleDir . '/lang/' . $manager->lang . '.php')) {
$langLabel = $manager->lang;
} elseif (is_file($moduleDir . '/lang/en.php')) {
$langLabel = 'en';
} elseif (($langs = array_slice(scandir($moduleDir . '/lang/'), 2)) && count($langs) > 0) {
$langLabel = str_replace('.php', '', reset($langs));
}
return $langLabel;
}
} Okay/Core/Notify.php 0000664 0000000 0000000 00000054771 13543155520 0014653 0 ustar 00root root 0000000 0000000 PHPMailer = $PHPMailer;
$this->settings = $settings;
$this->languages = $languages;
$this->design = $design;
$this->templateConfig = $templateConfig;
$this->ordersLogic = $ordersLogic;
$this->entityFactory = $entityFactory;
$this->backendTranslations = $backendTranslations;
$this->logger = $logger;
$this->rootDir = $rootDir;
}
/* SMTP отправка емейла*/
public function SMTP($to, $subject, $message)
{
$this->PHPMailer->IsSMTP(); // telling the class to use SMTP
$this->PHPMailer->Host = $this->settings->smtp_server;
$this->PHPMailer->SMTPDebug = 0;
$this->PHPMailer->SMTPAuth = true;
$this->PHPMailer->CharSet = 'utf-8';
$this->PHPMailer->Port = $this->settings->smtp_port;
if ($this->PHPMailer->Port == 465) {
$this->PHPMailer->SMTPSecure = "ssl";
// Добавляем протокол, если не указали
$this->PHPMailer->Host = (strpos($this->PHPMailer->Host, "ssl://") === false) ? "ssl://".$this->PHPMailer->Host : $this->PHPMailer->Host;
}
$this->PHPMailer->Username = $this->settings->smtp_user;
$this->PHPMailer->Password = $this->settings->smtp_pass;
$this->PHPMailer->SetFrom($this->settings->smtp_user, $this->settings->notify_from_name);
$this->PHPMailer->AddReplyTo($this->settings->smtp_user, $this->settings->notify_from_name);
$this->PHPMailer->Subject = $subject;
$this->PHPMailer->MsgHTML($message);
$this->PHPMailer->addCustomHeader("MIME-Version: 1.0\n");
$recipients = explode(',',$to);
if (!empty($recipients)) {
foreach ($recipients as $i=>$r) {
$this->PHPMailer->AddAddress($r);
}
} else {
$this->PHPMailer->AddAddress($to);
}
if ($this->PHPMailer->Send()) {
return;
}
if ($this->PHPMailer->SMTPDebug != 0) {
$this->logger->notice("Can`t send mail to '{$to}', ErrorInfo: {$this->PHPMailer->ErrorInfo}", ['subject' => $subject]);
} else {
$this->logger->notice("Can`t send mail to '{$to}', ErrorInfo: For view details should enable debug mode", ['subject' => $subject]);
}
}
/*Отправка емейла*/
public function email($to, $subject, $message, $from = '', $reply_to = '')
{
$headers = "MIME-Version: 1.0\n" ;
$headers .= "Content-type: text/html; charset=utf-8; \r\n";
$headers .= "From: $from\r\n";
if(!empty($reply_to)) {
$headers .= "reply-to: $reply_to\r\n";
}
$subject = "=?utf-8?B?".base64_encode($subject)."?=";
if ($this->settings->use_smtp) {
$this->SMTP($to, $subject, $message);
} else {
mail($to, $subject, $message, $headers);
}
}
/*Отправка емейла клиенту о заказе*/
public function emailOrderUser($orderId)
{
/** @var OrdersEntity $ordersEntity */
$ordersEntity = $this->entityFactory->get(OrdersEntity::class);
/** @var DeliveriesEntity $deliveriesEntity */
$deliveriesEntity = $this->entityFactory->get(DeliveriesEntity::class);
/** @var OrderStatusEntity $ordersStatusEntity */
$ordersStatusEntity = $this->entityFactory->get(OrderStatusEntity::class);
/** @var CurrenciesEntity $currenciesEntity */
$currenciesEntity = $this->entityFactory->get(CurrenciesEntity::class);
/** @var TranslationsEntity $translationsEntity */
$translationsEntity = $this->entityFactory->get(TranslationsEntity::class);
if (!($order = $ordersEntity->get(intval($orderId))) || empty($order->email)) {
return false;
}
/*lang_modify...*/
if (!empty($order->lang_id)) {
$currentLangId = $this->languages->getLangId();
$this->languages->setLangId($order->lang_id);
$currencies = $currenciesEntity->find(['enabled'=>1]);
// Берем валюту из сессии
if (isset($_SESSION['currency_id'])) {
$currency = $currenciesEntity->get((int)$_SESSION['currency_id']);
} else {
$currency = reset($currencies);
}
$this->design->assign("currency", $currency);
$this->settings->initSettings();
$this->design->assign('settings', $this->settings);
$this->design->assign('lang', $translationsEntity->find(array('lang_id'=>$order->lang_id)));
}
/*/lang_modify...*/
$purchases = $this->ordersLogic->getOrderPurchases($order->id);
$this->design->assign('purchases', $purchases);
// Способ доставки
$delivery = $deliveriesEntity->get($order->delivery_id);
$this->design->assign('delivery', $delivery);
$this->design->assign('order', $order);
$orderStatuses = $ordersStatusEntity->find(["status"=>intval($order->status_id)]);
$this->design->assign('order_status', reset($orderStatuses));
// Отправляем письмо
// Если в шаблон не передавалась валюта, передадим
if ($this->design->smarty->getTemplateVars('currency') === null) {
$this->design->assign('currency', current($currenciesEntity->find(['enabled'=>1])));
}
$emailTemplate = $this->design->fetch($this->rootDir.'design/'.$this->templateConfig->getTheme().'/html/email/email_order.tpl');
$subject = $this->design->get_var('subject');
$from = ($this->settings->notify_from_name ? $this->settings->notify_from_name." <".$this->settings->notify_from_email.">" : $this->settings->notify_from_email);
$this->email($order->email, $subject, $emailTemplate, $from);
/*lang_modify...*/
if (!empty($currentLangId)) {
$this->languages->setLangId($currentLangId);
$currencies = $currenciesEntity->find(['enabled'=>1]);
// Берем валюту из сессии
if (isset($_SESSION['currency_id'])) {
$currency = $currenciesEntity->get((int)$_SESSION['currency_id']);
} else {
$currency = reset($currencies);
}
$this->design->assign("currency", $currency);
$this->settings->initSettings();
$this->design->assign('settings', $this->settings);
}
/*/lang_modify...*/
}
/*Отправка емейла о заказе администратору*/
public function emailOrderAdmin($orderId)
{
/** @var OrdersEntity $ordersEntity */
$ordersEntity = $this->entityFactory->get(OrdersEntity::class);
/** @var DeliveriesEntity $deliveriesEntity */
$deliveriesEntity = $this->entityFactory->get(DeliveriesEntity::class);
/** @var UsersEntity $usersEntity */
$usersEntity = $this->entityFactory->get(UsersEntity::class);
/** @var OrderStatusEntity $ordersStatusEntity */
$ordersStatusEntity = $this->entityFactory->get(OrderStatusEntity::class);
/** @var CurrenciesEntity $currenciesEntity */
$currenciesEntity = $this->entityFactory->get(CurrenciesEntity::class);
if (!($order = $ordersEntity->get(intval($orderId)))) {
return false;
}
$purchases = $this->ordersLogic->getOrderPurchases($order->id);
$this->design->assign('purchases', $purchases);
// Способ доставки
$delivery = $deliveriesEntity->get($order->delivery_id);
$this->design->assign('delivery', $delivery);
// Пользователь
$user = $usersEntity->get(intval($order->user_id));
$this->design->assign('user', $user);
$this->design->assign('order', $order);
$orderStatuses = $ordersStatusEntity->find(["status"=>intval($order->status_id)]);
$this->design->assign('order_status', reset($orderStatuses));
// В основной валюте
$this->design->assign('main_currency', $currenciesEntity->getMainCurrency());
// Перевод админки
$backendTranslations = $this->backendTranslations;
$file = "backend/lang/".$this->settings->email_lang.".php";
if (!file_exists($file)) {
foreach (glob("backend/lang/??.php") as $f) {
$file = "backend/lang/".pathinfo($f, PATHINFO_FILENAME).".php";
break;
}
}
require($file);
$this->design->assign('btr', $backendTranslations);
// Отправляем письмо
$emailTemplate = $this->design->fetch($this->rootDir.'backend/design/html/email/email_order_admin.tpl');
$subject = $this->design->get_var('subject');
$this->email($this->settings->order_email, $subject, $emailTemplate, $this->settings->notify_from_email);
}
/*Отправка емейла о комментарии администратору*/
public function emailCommentAdmin($commentId)
{
/** @var CommentsEntity $commentsEntity */
$commentsEntity = $this->entityFactory->get(CommentsEntity::class);
/** @var ProductsEntity $productsEntity */
$productsEntity = $this->entityFactory->get(ProductsEntity::class);
/** @var BlogEntity $blogEntity */
$blogEntity = $this->entityFactory->get(BlogEntity::class);
if (!($comment = $commentsEntity->get(intval($commentId)))) {
return false;
}
if ($comment->type == 'product') {
$comment->product = $productsEntity->get(intval($comment->object_id));
} elseif ($comment->type == 'blog') {
$comment->post = $blogEntity->get(intval($comment->object_id));
} elseif ($comment->type == 'news') {
$comment->post = $blogEntity->get(intval($comment->object_id));
}
$this->design->assign('comment', $comment);
// Перевод админки
$backendTranslations = $this->backendTranslations;
$file = "backend/lang/".$this->settings->email_lang.".php";
if (!file_exists($file)) {
foreach (glob("backend/lang/??.php") as $f) {
$file = "backend/lang/".pathinfo($f, PATHINFO_FILENAME).".php";
break;
}
}
require($file);
$this->design->assign('btr', $backendTranslations);
// Отправляем письмо
$email_template = $this->design->fetch($this->rootDir.'backend/design/html/email/email_comment_admin.tpl');
$subject = $this->design->get_var('subject');
$this->email($this->settings->comment_email, $subject, $email_template, $this->settings->notify_from_email);
}
/*Отправка емейла администратору о заказе обратного звонка*/
public function emailCallbackAdmin($callbackId)
{
/** @var CallbacksEntity $callbacksEntity */
$callbacksEntity = $this->entityFactory->get(CallbacksEntity::class);
if (!($callback = $callbacksEntity->get(intval($callbackId)))) {
return false;
}
$this->design->assign('callback', $callback);
$backendTranslations = $this->backendTranslations;
$file = "backend/lang/".$this->settings->email_lang.".php";
if (!file_exists($file)) {
foreach (glob("backend/lang/??.php") as $f) {
$file = "backend/lang/".pathinfo($f, PATHINFO_FILENAME).".php";
break;
}
}
require($file);
$this->design->assign('btr', $backendTranslations);
// Отправляем письмо
$email_template = $this->design->fetch($this->rootDir.'backend/design/html/email/email_callback_admin.tpl');
$subject = $this->design->get_var('subject');
$this->email($this->settings->comment_email, $subject, $email_template, "$callback->name <$callback->phone>", "$callback->name <$callback->phone>");
}
/*Отправка емейла с ответом на комментарий клиенту*/
public function emailCommentAnswerToUser($commentId)
{
/** @var CommentsEntity $commentsEntity */
$commentsEntity = $this->entityFactory->get(CommentsEntity::class);
/** @var TranslationsEntity $translationsEntity */
$translationsEntity = $this->entityFactory->get(TranslationsEntity::class);
/** @var ProductsEntity $productsEntity */
$productsEntity = $this->entityFactory->get(ProductsEntity::class);
/** @var BlogEntity $blogEntity */
$blogEntity = $this->entityFactory->get(BlogEntity::class);
if(!($comment = $commentsEntity->get(intval($commentId)))
|| !($parentComment = $commentsEntity->get(intval($comment->parent_id)))
|| !$parentComment->email) {
return false;
}
$templateDir = $this->design->getTemplatesDir();
$compiledDir = $this->design->getCompiledDir();
$this->design->setTemplatesDir('design/'.$this->templateConfig->getTheme().'/html');
$this->design->setCompiledDir('compiled/' . $this->templateConfig->getTheme());
/*lang_modify...*/
if (!empty($parentComment->lang_id)) {
$currentLangId = $this->languages->getLangId();
$this->languages->setLangId($parentComment->lang_id);
$this->settings->initSettings();
$this->design->assign('settings', $this->settings);
$this->design->assign('lang', $translationsEntity->find(array('lang_id'=>$parentComment->lang_id)));
}
/*/lang_modify...*/
if ($comment->type == 'product') {
$comment->product = $productsEntity->get(intval($comment->object_id));
} elseif ($comment->type == 'blog') {
$comment->post = $blogEntity->get(intval($comment->object_id));
} elseif ($comment->type == 'news') {
$comment->post = $blogEntity->get(intval($comment->object_id));
}
$this->design->assign('comment', $comment);
$this->design->assign('parent_comment', $parentComment);
// Отправляем письмо
$emailTemplate = $this->design->fetch($this->rootDir.'design/'.$this->templateConfig->getTheme().'/html/email/email_comment_answer_to_user.tpl');
$subject = $this->design->get_var('subject');
$from = ($this->settings->notify_from_name ? $this->settings->notify_from_name." <".$this->settings->notify_from_email.">" : $this->settings->notify_from_email);
$this->email($parentComment->email, $subject, $emailTemplate, $from, $from);
$this->design->setTemplatesDir($templateDir);
$this->design->setCompiledDir($compiledDir);
/*lang_modify...*/
if (!empty($currentLangId)) {
$this->languages->setLangId($currentLangId);
$this->settings->initSettings();
$this->design->assign('settings', $this->settings);
}
/*/lang_modify...*/
}
/*Отправка емейла о восстановлении пароля клиенту*/
public function emailPasswordRemind($userId, $code)
{
/** @var UsersEntity $usersEntity */
$usersEntity = $this->entityFactory->get(UsersEntity::class);
/** @var TranslationsEntity $translationsEntity */
$translationsEntity = $this->entityFactory->get(TranslationsEntity::class);
if(!($user = $usersEntity->get(intval($userId)))) {
return false;
}
$currentLangId = $this->languages->getLangId();
$this->settings->initSettings();
$this->design->assign('settings', $this->settings);
$this->design->assign('lang', $translationsEntity->find(['lang_id'=>$currentLangId]));
$this->design->assign('user', $user);
$this->design->assign('code', $code);
// Отправляем письмо
$email_template = $this->design->fetch($this->rootDir.'design/'.$this->templateConfig->getTheme().'/html/email/email_password_remind.tpl');
$subject = $this->design->get_var('subject');
$from = ($this->settings->notify_from_name ? $this->settings->notify_from_name." <".$this->settings->notify_from_email.">" : $this->settings->notify_from_email);
$this->email($user->email, $subject, $email_template, $from);
$this->design->smarty->clearAssign('user');
$this->design->smarty->clearAssign('code');
}
/*Отправка емейла о заявке с формы обратной связи администратору*/
public function emailFeedbackAdmin($feedbackId)
{
/** @var UsersEntity $feedbackEntity */
$feedbackEntity = $this->entityFactory->get(FeedbacksEntity::class);
if (!($feedback = $feedbackEntity->get(intval($feedbackId)))) {
return false;
}
$this->design->assign('feedback', $feedback);
// Перевод админки
$backendTranslations = $this->backendTranslations;
$file = "backend/lang/".$this->settings->email_lang.".php";
if (!file_exists($file)) {
foreach (glob("backend/lang/??.php") as $f) {
$file = "backend/lang/".pathinfo($f, PATHINFO_FILENAME).".php";
break;
}
}
require($file);
$this->design->assign('btr', $backendTranslations);
// Отправляем письмо
$email_template = $this->design->fetch($this->rootDir.'backend/design/html/email/email_feedback_admin.tpl');
$subject = $this->design->get_var('subject');
$this->email($this->settings->comment_email, $subject, $email_template, "$feedback->name <$feedback->email>", "$feedback->name <$feedback->email>");
}
/*Отправка емейла с ответом на заявку с формы обратной связи клиенту*/
public function emailFeedbackAnswerFoUser($comment_id,$text)
{
/** @var FeedbacksEntity $feedbackEntity */
$feedbackEntity = $this->entityFactory->get(FeedbacksEntity::class);
/** @var TranslationsEntity $translationsEntity */
$translationsEntity = $this->entityFactory->get(TranslationsEntity::class);
if(!($feedback = $feedbackEntity->get(intval($comment_id)))) {
return false;
}
$templateDir = $this->design->getTemplatesDir();
$compiledDir = $this->design->getCompiledDir();
$this->design->setTemplatesDir('design/'.$this->templateConfig->getTheme().'/html');
$this->design->setCompiledDir('compiled/' . $this->templateConfig->getTheme());
/*lang_modify...*/
if (!empty($feedback->lang_id)) {
$currentLangId = $this->languages->getLangId();
$this->languages->setLangId($feedback->lang_id);
$this->design->assign('lang', $translationsEntity->find(['lang_id'=>$feedback->lang_id]));
}
/*/lang_modify...*/
$this->design->assign('feedback', $feedback);
$this->design->assign('text', $text);
// Отправляем письмо
$email_template = $this->design->fetch($this->rootDir.'design/'.$this->templateConfig->getTheme().'/html/email/email_feedback_answer_to_user.tpl');
$subject = $this->design->get_var('subject');
$from = ($this->settings->notify_from_name ? $this->settings->notify_from_name." <".$this->settings->notify_from_email.">" : $this->settings->notify_from_email);
$this->email($feedback->email, $subject, $email_template, $from, $from);
$this->design->setTemplatesDir($templateDir);
$this->design->setCompiledDir($compiledDir);
/*lang_modify...*/
if (!empty($currentLangId)) {
$this->languages->setLangId($currentLangId);
}
/*/lang_modify...*/
}
/*Отправка емейла на восстановление пароля администратора*/
public function passwordRecoveryAdmin($email, $code)
{
if(empty($email) || empty($code)){
return false;
}
// Перевод админки
$backendTranslations = $this->backendTranslations;
$file = "backend/lang/".$this->settings->email_lang.".php";
if (!file_exists($file)) {
foreach (glob("backend/lang/??.php") as $f) {
$file = "backend/lang/".pathinfo($f, PATHINFO_FILENAME).".php";
break;
}
}
require($file);
$this->design->assign('btr', $backendTranslations);
$this->design->assign('code',$code);
$this->design->assign('recovery_url', 'backend/index.php?module=AuthAdmin&code='.$code);
$email_template = $this->design->fetch($this->rootDir.'backend/design/html/email/email_admin_recovery.tpl');
$subject = $this->design->get_var('subject');
$from = ($this->settings->notify_from_name ? $this->settings->notify_from_name." <".$this->settings->notify_from_email.">" : $this->settings->notify_from_email);
$this->email($email, $subject, $email_template, $from, $from);
return true;
}
}
Okay/Core/TemplateConfig.php 0000664 0000000 0000000 00000062704 13543155520 0016277 0 ustar 00root root 0000000 0000000 modules = $modules;
$this->module = $module;
$this->rootDir = $rootDir;
$this->scriptsDefer = $scriptsDefer;
$this->themeSettingsFileName = $themeSettingsFileName;
$this->compileCssDir = $compileCssDir;
$this->compileJsDir = $compileJsDir;
}
/**
* @param $theme
* @param $adminTheme
* @param $adminThemeManagers
* @throws \Exception
*
* Метод конфигуратор, нужен, чтобы не передавать в зависимости целый класс Settings
*/
public function configure($theme, $adminTheme, $adminThemeManagers)
{
$this->theme = $theme;
$this->adminTheme = $adminTheme;
$this->adminThemeManagers = $adminThemeManagers;
$this->settingsFile = 'design/' . $this->getTheme() . '/css/' . $this->themeSettingsFileName;
if (($themeJs = include 'design/' . $this->getTheme() . '/js.php') && is_array($themeJs)) {
foreach ($themeJs as $jsItem) {
$this->registerJs($jsItem);
}
}
if (($themeCss = include 'design/' . $this->getTheme() . '/css.php') && is_array($themeCss)) {
foreach ($themeCss as $cssItem) {
$this->registerCss($cssItem);
}
}
$runningModules = $this->modules->getRunningModules();
foreach ($runningModules as $runningModule) {
$moduleThemesDir = $this->module->getModuleDirectory($runningModule['vendor'], $runningModule['module_name']) . 'design/';
if (file_exists($moduleThemesDir . 'css.php') && ($moduleCss = include $moduleThemesDir . 'css.php') && is_array($moduleCss)) {
/** @var TemplateCss $cssItem */
foreach ($moduleCss as $cssItem) {
if ($cssItem->getDir() === null) {
$cssItem->setDir($moduleThemesDir . 'css/');
}
$this->registerCss($cssItem);
}
}
if (file_exists($moduleThemesDir . 'js.php') && ($moduleJs = include $moduleThemesDir . 'js.php') && is_array($moduleJs)) {
/** @var TemplateJs $jsItem */
foreach ($moduleJs as $jsItem) {
if ($jsItem->getDir() === null) {
$jsItem->setDir($moduleThemesDir . 'js/');
}
$this->registerJs($jsItem);
}
}
}
}
public function __destruct()
{
// Инвалидация компилированных js и css файлов
$css = glob($this->rootDir . $this->compileCssDir . $this->getTheme() . ".*.css");
$js = glob($this->rootDir . $this->compileJsDir . $this->getTheme() . ".*.js");
$cacheFiles = array_merge($css, $js);
if (is_array($cacheFiles)) {
foreach ($cacheFiles as $f) {
$fileTime = filemtime($f);
// Если файл редактировался более недели назад, удалим его, вероятнее всего он уже не нужен
if ($fileTime !== false && time() - $fileTime > 604800) {
@unlink($f);
}
}
}
}
private function registerCss(TemplateCss $css)
{
// Файл настроек шаблона регистрировать не нужно
if ($css->getFilename() != $this->themeSettingsFileName && $this->checkFile($css->getFilename(), 'css', $css->getDir()) === true) {
$fullPath = $this->getFullPath($css->getFilename(), 'css', $css->getDir());
$fileId = md5($fullPath);
if ($css->getIndividual() === true) {
$this->individualCss[$css->getPosition()][$fileId] = $fullPath;
} else {
$this->templateCss[$css->getPosition()][$fileId] = $fullPath;
}
}
}
private function registerJs(TemplateJs $js)
{
if ($this->checkFile($js->getFilename(), 'js', $js->getDir()) === true) {
$fullPath = $this->getFullPath($js->getFilename(), 'js', $js->getDir());
$fileId = md5($fullPath);
if ($js->getIndividual() === true) {
if ($js->getDefer() === true) {
$this->deferJsFiles[$fullPath] = $fullPath;
}
$this->individualJs[$js->getPosition()][$fileId] = $fullPath;
} else {
$this->templateJs[$js->getPosition()][$fileId] = $fullPath;
}
}
}
/**
* Метод возвращает теги на подключение всех зарегестрированных js и css для блока head
* @return string
*/
public function head()
{
return $this->getIncludeHtml('head');
}
/**
* Метод возвращает теги на подключение всех зарегестрированных js и css для футера
* @return string
* @throws \Exception
*/
public function footer()
{
$SL = new ServiceLocator();
/** @var Design $design */
$design = $SL->getService(Design::class);
/** @var EntityFactory $entityFactory */
$entityFactory = $SL->getService(EntityFactory::class);
/** @var ManagersEntity $managersEntity */
$managersEntity = $entityFactory->get(ManagersEntity::class);
$footer = $this->getIncludeHtml('footer');
if (!empty($_SESSION['admin']) && ($manager = $managersEntity->get($_SESSION['admin']))) {
$templatesDir = $design->getTemplatesDir();
$compiledDir = $design->getCompiledDir();
$design->setTemplatesDir('backend/design/html');
$design->setCompiledDir('backend/design/compiled');
// Перевод админки
$backendTranslations = new \stdClass();
$file = "backend/lang/" . $manager->lang . ".php";
if (!file_exists($file)) {
foreach (glob("backend/lang/??.php") as $f) {
$file = "backend/lang/" . pathinfo($f, PATHINFO_FILENAME) . ".php";
break;
}
}
include ($file);
$design->assign('scripts_defer', $this->scriptsDefer);
$design->assign('btr', $backendTranslations);
$footer .= $design->fetch('admintooltip.tpl');
// Возвращаем настройки компилирования файлов smarty
$design->setTemplatesDir($templatesDir);
$design->setCompiledDir($compiledDir);
}
// Подключаем динамический JS (scripts.tpl)
$dynamicJsFile = "design/" . $this->getTheme() . "/html/scripts.tpl";
if (is_file($dynamicJsFile)) {
$filename = md5_file($dynamicJsFile) . json_encode($_GET);
if (isset($_SESSION['dynamic_js'])) {
$filename .= json_encode($_SESSION['dynamic_js']);
}
$filename = md5($filename);
$getParams = (!empty($_GET) ? "?" . http_build_query($_GET) : '');
$footer .= "" . PHP_EOL;
}
return $footer;
}
/**
* Метод возвращает название активной темы. Нужно для того,
* чтобы логика определения темы под админом была в одном месте
* @return string Название темы
*/
public function getTheme()
{
if (!empty($this->theme)) {
return $this->theme;
}
$adminTheme = $this->adminTheme;
$adminThemeManagers = $this->adminThemeManagers;
if (!empty($_SESSION['admin']) && !empty($adminTheme) && $this->theme != $this->adminTheme) {
if (empty($adminThemeManagers) || in_array($_SESSION['admin'], $this->adminThemeManagers)) {
$this->theme = $this->adminTheme;
}
}
return $this->theme;
}
public function clearCompiled()
{
$cache_directories = [
$this->compileCssDir,
$this->compileJsDir,
];
foreach ($cache_directories as $dir) {
if (is_dir($dir)) {
foreach (scandir($dir) as $file) {
if (!in_array($file, array(".", ".."))) {
@unlink($dir . $file);
}
}
}
}
}
public function getCssVariables() {
if (empty($this->cssVariables)) {
$this->initCssVariables();
}
return $this->cssVariables;
}
public function updateCssVariables($variables)
{
if (empty($variables)) {
return false;
}
if (empty($this->cssVariables)) {
$this->initCssVariables();
}
$oCssParser = new Parser(file_get_contents($this->settingsFile));
$oCssDocument = $oCssParser->parse();
foreach ($oCssDocument->getAllRuleSets() as $oBlock) {
foreach ($oBlock->getRules() as $r) {
if (isset($variables[$r->getRule()])) {
$r->setValue($variables[$r->getRule()]);
$this->cssVariables[$r->getRule()] = $variables[$r->getRule()];
}
}
}
$result_file = '/**' . PHP_EOL;
$result_file .= '* Файл стилей для настройки шаблона.' . PHP_EOL;
$result_file .= '* Регистрировать этот файл для подключения в шаблоне не нужно' . PHP_EOL;
$result_file .= '*/' . PHP_EOL . PHP_EOL;
$result_file .= trim($oCssDocument->render(OutputFormat::createPretty())) . PHP_EOL;
file_put_contents($this->settingsFile, $result_file);
}
public function compileIndividualCss($filename, $dir = null)
{
if ($filename != $this->themeSettingsFileName && $this->checkFile($filename, 'css', $dir) === true) {
$file = $this->getFullPath($filename, 'css', $dir);
$hash = md5_file($file) . md5_file($this->settingsFile);
$compiled_filename = $this->compileCssDir . $this->getTheme() . '.' . pathinfo($file, PATHINFO_BASENAME) . '.' . $hash . '.css';
if (file_exists($compiled_filename)) {
// Обновляем дату редактирования файла, чтобы он не инвалидировался
touch($compiled_filename);
} else {
$result_file = $this->compileCssFile($file);
$this->saveCompileFile($result_file, $compiled_filename);
}
return !empty($compiled_filename) ? "" . PHP_EOL : '';
}
return '';
}
public function compileIndividualJs($filename, $dir = null, $defer = false)
{
if ($this->checkFile($filename, 'js', $dir) === true) {
$file = $this->getFullPath($filename, 'js', $dir);
$compiled_filename = $this->compileJsDir . $this->getTheme() . '.' . pathinfo($file, PATHINFO_BASENAME) . '.' . md5_file($file) . '.js';
if (file_exists($compiled_filename)) {
// Обновляем дату редактирования файла, чтобы он не инвалидировался
touch($compiled_filename);
} else {
$result_file = file_get_contents($file) . PHP_EOL . PHP_EOL;
$minifier = new JS();
$minifier->add($result_file);
$result_file = $minifier->minify();
$this->saveCompileFile($result_file, $compiled_filename);
}
return !empty($compiled_filename) ? "" . PHP_EOL : '';
}
return '';
}
public function minifyJs($jsString)
{
$minifier = new JS();
$minifier->add($jsString);
$dynamicJs = $minifier->minify();
return $dynamicJs;
}
/**
* @param string $position
* @return string html для подключения js и css шаблона
*/
private function getIncludeHtml($position = 'head')
{
$include_html = '';
// Подключаем основной файл стилей
if (($css_filename = $this->compileRegisteredCss($position)) !== '') {
$include_html .= "" . PHP_EOL;
}
// Подключаем дополнительные индивидуальные файлы стилей
if (($individualCss_filenames = $this->compileRegisteredIndividualCss($position)) !== []) {
foreach ($individualCss_filenames as $filename) {
$include_html .= "" . PHP_EOL;
}
}
// Подключаем основной JS файл
if (($js_filename = $this->compileRegisteredJs($position)) !== '') {
$include_html .= "" . PHP_EOL;
}
// Подключаем дополнительные индивидуальные JS файлы
if (($individualJs_filenames = $this->compileRegisteredIndividualJs($position)) !== []) {
foreach ($individualJs_filenames as $filename) {
$include_html .= "" . PHP_EOL;
}
}
return $include_html;
}
private function compileRegisteredIndividualJs($position)
{
$result = [];
if (!empty($this->individualJs[$position])) {
foreach ($this->individualJs[$position] as $k=>$file) {
$compiled_filename = $this->compileJsDir . $this->getTheme() . '.' . pathinfo($file, PATHINFO_BASENAME) . '.' . md5_file($file) . '.js';
$result[] = $compiled_filename;
if (isset($this->deferJsFiles[$file])) {
$this->deferJsFiles[$compiled_filename] = $compiled_filename;
unset($this->deferJsFiles[$file]);
}
if (file_exists($compiled_filename)) {
// Обновляем дату редактирования файла, чтобы он не инвалидировался
touch($compiled_filename);
} else {
$result_file = file_get_contents($file) . PHP_EOL . PHP_EOL;
$minifier = new JS();
$minifier->add($result_file);
$result_file = $minifier->minify();
$this->saveCompileFile($result_file, $compiled_filename);
}
// Удаляем скомпилированный файл из зарегистрированных, чтобы он повторно не компилировался
unset($this->individualCss[$position][$k]);
}
}
return $result;
}
private function compileRegisteredIndividualCss($position)
{
$result = [];
if (!empty($this->individualCss[$position])) {
foreach ($this->individualCss[$position] as $k=>$file) {
$hash = md5_file($file) . md5_file($this->settingsFile);
$compiled_filename = $this->compileCssDir . $this->getTheme() . '.' . pathinfo($file, PATHINFO_BASENAME) . '.' . $hash . '.css';
$result[] = $compiled_filename;
if (file_exists($compiled_filename)) {
// Обновляем дату редактирования файла, чтобы он не инвалидировался
touch($compiled_filename);
} else {
$result_file = $this->compileCssFile($file);
$this->saveCompileFile($result_file, $compiled_filename);
}
// Удаляем скомпилированный файл из зарегистрированных, чтобы он повторно не компилировался
unset($this->individualJs[$position][$k]);
}
}
return $result;
}
/**
* @param $position //head|footer указание куда файл генерится
* Метод компилирует все зарегистрированные, через метод registerCss(), CSS файлы
* Собитаются они в одном общем выходном файле, в кеше
* Также здесь подставляются значения переменных CSS.
* @return string|null
*/
private function compileRegisteredCss($position)
{
$result_file = '';
$compiled_filename = '';
if (!empty($this->templateCss[$position])) {
// Определяем название выходного файла, на основании хешей всех входящих файлов
foreach ($this->templateCss[$position] as $file) {
$compiled_filename .= md5_file($file) . md5_file($this->settingsFile);
}
$compiled_filename = $this->compileCssDir . $this->getTheme() . '.' . $position . '.' . md5($compiled_filename) . '.css';
// Если файл уже скомпилирован, отдаем его.
if (file_exists($compiled_filename)) {
// Обновляем дату редактирования файла, чтобы он не инвалидировался
touch($compiled_filename);
return $compiled_filename;
}
foreach ($this->templateCss[$position] as $k=>$file) {
$result_file .= $this->compileCssFile($file);
// Удаляем скомпилированный файл из зарегистрированных, чтобы он повторно не компилировался
unset($this->templateCss[$position][$k]);
}
}
$this->saveCompileFile($result_file, $compiled_filename);
return $compiled_filename;
}
/**
* Метод компилирует все зарегистрированные JS файлы
* @param $position (head|footer)
* @return string compiled filename
*/
private function compileRegisteredJs($position)
{
$result_file = '';
$compiled_filename = '';
if (!empty($this->templateJs[$position])) {
// Определяем название выходного файла, на основании хешей всех входящих файлов
foreach ($this->templateJs[$position] as $file) {
$compiled_filename .= md5_file($file);
}
$compiled_filename = $this->compileJsDir . $this->getTheme() . '.' . $position . '.' . md5($compiled_filename) . '.js';
// Если файл уже скомпилирован, отдаем его.
if (file_exists($compiled_filename)) {
// Обновляем дату редактирования файла, чтобы он не инвалидировался
touch($compiled_filename);
return $compiled_filename;
}
foreach ($this->templateJs[$position] as $k=>$file) {
$filename = pathinfo($file, PATHINFO_BASENAME);
$result_file .= '/*! #File ' . $filename . ' */' . PHP_EOL;
$result_file .= file_get_contents($file) . PHP_EOL . PHP_EOL;
// Удаляем скомпилированный файл из зарегистрированных, чтобы он повторно не компилировался
unset($this->templateJs[$position][$k]);
}
}
$minifier = new JS();
$minifier->add($result_file);
$result_file = $minifier->minify();
$this->saveCompileFile($result_file, $compiled_filename);
return $compiled_filename;
}
/**
* @param $content
* @param $file
* Метод сохраняет скомпилированный css в кеш
*/
private function saveCompileFile($content, $file) {
$dir = pathinfo($file, PATHINFO_DIRNAME);
if(!empty($dir) && !is_dir($dir)) {
mkdir($dir, 0777, true);
}
if (!empty($content)) {
// Сохраняем скомпилированный CSS
file_put_contents($file, $content);
}
}
private function initCssVariables() {
if (empty($this->cssVariables) && file_exists($this->settingsFile)) {
$oCssParser = new Parser(file_get_contents($this->settingsFile));
$oCssDocument = $oCssParser->parse();
foreach ($oCssDocument->getAllRuleSets() as $oBlock) {
foreach ($oBlock->getRules() as $r) {
$css_value = (string)$r->getValue();
if (strpos($r->getRule(), '--') === 0) {
$this->cssVariables[$r->getRule()] = $css_value;
}
}
}
}
}
private function compileCssFile($file)
{
if (empty($this->cssVariables)) {
$this->initCssVariables();
}
// Вычисляем директорию, для подключения ресурсов из css файла (background-image: url() etc.)
$sub_dir = trim(substr(pathinfo($file, PATHINFO_DIRNAME), strlen($this->rootDir)), "/\\");
$sub_dir = dirname($sub_dir);
$oCssParser = new Parser(file_get_contents($file));
$oCssDocument = $oCssParser->parse();
foreach ($oCssDocument->getAllRuleSets() as $oBlock) {
foreach ($oBlock->getRules() as $r) {
$css_value = (string)$r->getValue();
// Переназначаем переменные из файла настроек шаблона
$var = preg_replace('~^var\((.+)?\)$~', '$1', $css_value);
if (isset($this->cssVariables[$var])) {
$r->setValue($this->cssVariables[$var]);
}
// Перебиваем в файле все относительные пути
if (strpos($css_value, 'url') !== false && strpos($css_value, '..') !== false) {
$css_value = strtr($css_value, ['../' => '../../' . $sub_dir . '/']);
$r->setValue($css_value);
}
}
}
$filename = pathinfo($file, PATHINFO_BASENAME);
$result_file = '/***** #File ' . $filename . ' *****/' . PHP_EOL;
$result_file .= trim($oCssDocument->render(OutputFormat::createCompact())) . PHP_EOL;
unset($oCssParser);
return $result_file;
}
private function checkFile($filename, $type, $dir = null)
{
// файлы по http регистрировать нельзя
if (preg_match('~^(https?:)?//~', $filename)) {
return false;
}
$file = $this->getFullPath($filename, $type, $dir);
return (bool)file_exists($file);
}
private function getFullPath($filename, $type, $dir = null)
{
$directory = $this->rootDir;
if ($dir !== null) {
$directory .= trim($dir, ' \t\n\r\0\x0B/') . '/';
} else {
$directory .= 'design/' . $this->getTheme() . '/' . $type . '/';
}
return $directory . $filename;
}
}
Okay/Core/config/ 0000775 0000000 0000000 00000000000 13543155520 0014121 5 ustar 00root root 0000000 0000000 Okay/Core/config/parameters.php 0000664 0000000 0000000 00000006662 13543155520 0017007 0 ustar 00root root 0000000 0000000 [
'class' => Money::class,
'arguments' => [
new SR(EntityFactory::class),
],
'calls' => [
[
'method' => 'configure',
'arguments' => [
new PR('money.thousands_separator'),
]
],
]
],
*/
return [
'root_dir' => '{$root_dir}',
'logger' => [
'file' => __DIR__ . '/../../log/app.log',
],
'db' => [
'driver' => '{$db_driver}',
'dsn' => '{$db_driver}:host={$db_server};dbname={$db_name};charset={$db_charset}',
'user' => '{$db_user}',
'password' => '{$db_password}',
'prefix' => '{$db_prefix}',
'db_sql_mode' => '{$db_sql_mode}',
'db_timezone' => '{$db_timezone}',
'db_names' => '{$db_names}',
],
'config' => [
'config_file' => __DIR__ . '/../../../config/config.php',
'config_local_file' => __DIR__ . '/../../../config/config.local.php',
],
'template_config' => [
'scripts_defer' => '{$scripts_defer}',
'them_settings_filename' => 'theme-settings.css',
'compile_css_dir' => 'cache/css/',
'compile_js_dir' => 'cache/js/',
],
/**
* Настройки адапреров системы. Адапрер это по сути класс, который лежит в Okay\Core\Adapters\XXX
* Где XXX уже подвид адапреров
*/
'adapters' => [
'resize' => [
'default_adapter' => '{$resize_adapter}',
'watermark' => '{$watermark_file}',
'watermark_offset_x' => '{%watermark_offset_x%}',
'watermark_offset_y' => '{%watermark_offset_y%}',
'image_quality' => '{%image_quality%}',
],
'response' => [
'default_adapter' => 'Html',
],
],
'money' => [
'decimals_point' => '{%decimals_point%}',
'thousands_separator' => '{%thousands_separator%}',
],
'theme' => [
'name' => '{%theme%}',
'admin_theme_name' => '{%admin_theme%}',
'admin_theme_managers' => '{%admin_theme_managers%}',
],
'plugins' => [
'date' => [
'date_format' => '{%date_format%}',
],
],
'design' => [
'smarty_caching' => '{$smarty_caching}',
'smarty_debugging' => '{$smarty_debugging}',
'smarty_html_minify' => '{$smarty_html_minify}',
'smarty_compile_check' => '{$smarty_compile_check}',
'smarty_security' => '{$smarty_security}',
'smarty_cache_lifetime' => '{$smarty_cache_lifetime}',
],
];
Okay/Core/config/services.php 0000664 0000000 0000000 00000025707 13543155520 0016470 0 ustar 00root root 0000000 0000000 [
'class' => BRouter::class,
],
License::class => [
'class' => License::class,
],
PHPMailer::class => [
'class' => PHPMailer::class,
],
Smarty::class => [
'class' => Smarty::class,
],
Mobile_Detect::class => [
'class' => Mobile_Detect::class,
],
Router::class => [
'class' => Router::class,
'arguments' => [
new SR(BRouter::class),
new SR(Request::class),
new SR(Response::class),
new SR(License::class),
new SR(EntityFactory::class),
new SR(Languages::class),
],
],
Config::class => [
'class' => Config::class,
'arguments' => [
new PR('config.config_file'),
new PR('config.config_local_file'),
],
],
Database::class => [
'class' => Database::class,
'arguments' => [
new SR(ExtendedPdo::class),
new SR(License::class),
new SR(LoggerInterface::class),
new PR('db'),
new SR(QueryFactory::class),
],
],
AuraQueryFactory::class => [
'class' => AuraQueryFactory::class,
'arguments' => [
new PR('db.driver'),
],
],
QueryFactory::class => [
'class' => QueryFactory::class,
'arguments' => [
new SR(AuraQueryFactory::class),
],
],
ExtendedPdo::class => [
'class' => ExtendedPdo::class,
'arguments' => [
new PR('db.dsn'),
new PR('db.user'),
new PR('db.password'),
],
],
EntityFactory::class => [
'class' => EntityFactory::class,
'arguments' => [
new SR(LoggerInterface::class),
],
],
Request::class => [
'class' => Request::class,
],
Response::class => [
'class' => Response::class,
'arguments' => [
new SR(Adapters\Response\AdapterManager::class),
new SR(License::class),
],
],
Languages::class => [
'class' => Languages::class,
'arguments' => [
new SR(Database::class),
new SR(Request::class),
new SR(QueryFactory::class),
],
],
Validator::class => [
'class' => Validator::class,
'arguments' => [
new SR(Settings::class),
new SR(Recaptcha::class),
],
],
Settings::class => [
'class' => Settings::class,
'arguments' => [
new SR(Database::class),
new SR(Languages::class),
new SR(QueryFactory::class),
],
],
TemplateConfig::class => [
'class' => TemplateConfig::class,
'arguments' => [
new SR(Modules::class),
new SR(Module::class),
new PR('root_dir'),
new PR('template_config.scripts_defer'),
new PR('template_config.them_settings_filename'),
new PR('template_config.compile_css_dir'),
new PR('template_config.compile_js_dir'),
],
'calls' => [
[
'method' => 'configure',
'arguments' => [
new PR('theme.name'),
new PR('theme.admin_theme_name'),
new PR('theme.admin_theme_managers'),
]
],
]
],
Design::class => [
'class' => Design::class,
'arguments' => [
new SR(Smarty::class),
new SR(Mobile_Detect::class),
new SR(TemplateConfig::class),
new PR('design.smarty_cache_lifetime'),
new PR('design.smarty_compile_check'),
new PR('design.smarty_html_minify'),
new PR('design.smarty_debugging'),
new PR('design.smarty_security'),
new PR('design.smarty_caching'),
new PR('root_dir'),
],
],
Image::class => [
'class' => Image::class,
'arguments' => [
new SR(Settings::class),
new SR(Config::class),
new SR(Adapters\Resize\AdapterManager::class),
new SR(Request::class),
new SR(Response::class),
new SR(QueryFactory::class),
new SR(Database::class),
new SR(EntityFactory::class),
new PR('root_dir'),
],
],
Notify::class => [
'class' => Notify::class,
'arguments' => [
new SR(Settings::class),
new SR(Languages::class),
new SR(EntityFactory::class),
new SR(Design::class),
new SR(TemplateConfig::class),
new SR(\Okay\Logic\OrdersLogic::class),
new SR(BackendTranslations::class),
new SR(PHPMailer::class),
new SR(LoggerInterface::class),
new PR('root_dir'),
],
],
Money::class => [
'class' => Money::class,
'arguments' => [
new SR(EntityFactory::class),
],
'calls' => [
[
'method' => 'configure',
'arguments' => [
new PR('money.decimals_point'),
new PR('money.thousands_separator'),
]
],
]
],
StreamHandler::class => [
'class' => StreamHandler::class,
'arguments' => [
new PR('logger.file'),
Logger::DEBUG,
],
],
LoggerInterface::class => [
'class' => Logger::class,
'arguments' => [ 'channel-name' ],
'calls' => [
[
'method' => 'pushHandler',
'arguments' => [
new SR(StreamHandler::class),
]
],
]
],
Recaptcha::class => [
'class' => Recaptcha::class,
'arguments' => [
new SR(Settings::class),
new SR(Request::class),
],
],
Managers::class => [
'class' => Managers::class,
],
Translit::class => [
'class' => Translit::class,
],
ManagerMenu::class => [
'class' => ManagerMenu::class,
'arguments' => [
new SR(Managers::class),
new SR(Module::class),
],
],
BackendTranslations::class => [
'class' => BackendTranslations::class,
],
JsSocial::class => [
'class' => JsSocial::class,
],
DataCleaner::class => [
'class' => DataCleaner::class,
'arguments' => [
new SR(Database::class),
new SR(Config::class),
new SR(QueryFactory::class),
],
],
ImportCore::class => [
'class' => ImportCore::class
],
Cart::class => [
'class' => Cart::class,
'arguments' => [
new SR(EntityFactory::class),
new SR(Settings::class),
new SR(ProductsLogic::class),
new SR(\Okay\Logic\MoneyLogic::class),
],
],
Comparison::class => [
'class' => Comparison::class,
'arguments' => [
new SR(EntityFactory::class),
new SR(Settings::class),
],
],
WishList::class => [
'class' => WishList::class,
'arguments' => [
new SR(EntityFactory::class),
new SR(Settings::class),
new SR(MoneyLogic::class),
],
],
ModulesEntitiesFilters::class => [
'class' => ModulesEntitiesFilters::class,
],
Module::class => [
'class' => Module::class,
],
Modules::class => [
'class' => Modules::class,
'arguments' => [
new SR(EntityFactory::class),
new SR(License::class),
new SR(Module::class),
new SR(QueryFactory::class),
new SR(Database::class),
],
],
Installer::class => [
'class' => Installer::class,
'arguments' => [
new SR(EntityFactory::class),
new SR(Module::class),
],
],
Support::class => [
'class' => Support::class,
'arguments' => [
new SR(Config::class),
new SR(Settings::class),
new SR(EntityFactory::class),
],
],
EntityMigrator::class => [
'class' => EntityMigrator::class,
'arguments' => [
new SR(Database::class),
new SR(QueryFactory::class),
new SR(SqlPresentor::class),
],
],
SqlPresentor::class => [
'class' => SqlPresentor::class,
],
UpdateObject::class => [
'class' => UpdateObject::class,
],
//> Logic classes
ProductsLogic::class => [
'class' => ProductsLogic::class,
'arguments' => [
new SR(EntityFactory::class),
new SR(MoneyLogic::class),
],
],
CatalogLogic::class => [
'class' => CatalogLogic::class,
'arguments' => [
new SR(EntityFactory::class),
new SR(Money::class)
],
],
OrdersLogic::class => [
'class' => OrdersLogic::class,
'arguments' => [
new SR(EntityFactory::class),
new SR(ProductsLogic::class),
new SR(\Okay\Logic\MoneyLogic::class),
],
],
FilterLogic::class => [
'class' => FilterLogic::class,
'arguments' => [
new SR(EntityFactory::class),
new SR(Settings::class),
new SR(Languages::class),
new SR(Request::class),
new SR(Router::class),
new SR(Design::class),
],
],
MoneyLogic::class => [
'class' => MoneyLogic::class,
'arguments' => [
new SR(EntityFactory::class),
],
],
FeaturesLogic::class => [
'class' => FeaturesLogic::class,
'arguments' => [
new SR(Database::class),
new SR(Import::class),
new SR(Translit::class),
new SR(EntityFactory::class),
new SR(QueryFactory::class),
]
],
//> Logic
];
$adapters = include __DIR__ . '/../Adapters/adapters.php';
return array_merge($services, $adapters);
Okay/Modules/ 0000775 0000000 0000000 00000000000 13543155520 0013374 5 ustar 00root root 0000000 0000000 Okay/Modules/OkayCMS/ 0000775 0000000 0000000 00000000000 13543155520 0014642 5 ustar 00root root 0000000 0000000 Okay/Modules/OkayCMS/GoogleMerchant/ 0000775 0000000 0000000 00000000000 13543155520 0017540 5 ustar 00root root 0000000 0000000 Okay/Modules/OkayCMS/GoogleMerchant/design/ 0000775 0000000 0000000 00000000000 13543155520 0021011 5 ustar 00root root 0000000 0000000 Okay/Modules/OkayCMS/GoogleMerchant/design/html/ 0000775 0000000 0000000 00000000000 13543155520 0021755 5 ustar 00root root 0000000 0000000 Okay/Modules/OkayCMS/GoogleMerchant/design/html/feed.xml.tpl 0000664 0000000 0000000 00000006633 13543155520 0024210 0 ustar 00root root 0000000 0000000
{if $settings->okaycms__google_merchant__company}
{$settings->okaycms__google_merchant__company}
{/if}
{$rootUrl}
{foreach $products as $p}
{foreach $p->variants as $v}
{if !$settings->okaycms__google_merchant__upload_non_exists_products_to_google && $v->stock === '0'}{continue}{/if}
{if $settings->okaycms__google_merchant__no_export_without_price == 1 && $v->price == 0}{continue}{/if}
-
{if $settings->okaycms__google_merchant__use_variant_name_like_size}
{$p->name|escape}
{if $v->name}{$v->name|escape}{/if}
{else}
{$p->name|escape}{if !empty($v->name)} {$v->name|escape}{/if}
{/if}
{url_generator route="product" url=$p->url absolute=1}{if !$v@first}?variant={$v->id}{/if}
{if $settings->okaycms__google_merchant__use_full_description_to_google}{$p->description|strip_tags|escape}{else}{$p->annotation|strip_tags|escape}{/if}
{$v->id}
new
{if round($v->compare_price|convert:$main_currency->id:false, 2) > round($v->price|convert:$main_currency->id:false, 2)}
{round($v->compare_price|convert:$main_currency->id:false, 2)} {$main_currency->code}
{round($v->price|convert:$main_currency->id:false, 2)} {$main_currency->code}
{else}
{round($v->price|convert:$main_currency->id:false, 2)} {$main_currency->code}
{/if}
{if $v->stock !== 0}in stock{else}not in stock{/if}
{if isset($all_brands[$p->brand_id])}
{$all_brands[$p->brand_id]->name|escape}
{/if}
{if $settings->okaycms__google_merchant__adult}true{else}false{/if}
{if $p->color}
{$p->color}
{/if}
{if $p->product_type}
{$p->product_type}
{/if}
{if !empty($p->images)}
{foreach $p->images as $image}
{if $image@first}
{$image->filename|resize:800:600}
{else}
{$image->filename|resize:800:600}
{/if}
{if $image@iteration == 10}{break}{/if}
{/foreach}
{/if}
{/foreach}
{/foreach}