'log', 'primary' => 'id_log', 'fields' => [ 'severity' => ['type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true], 'error_code' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'], 'message' => ['type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => true, 'size' => FormattedTextareaType::LIMIT_MEDIUMTEXT_UTF8_MB4], 'object_id' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'], 'id_shop' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'allow_null' => true], 'id_shop_group' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'allow_null' => true], 'id_lang' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'allow_null' => true], 'in_all_shops' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], 'id_employee' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'], 'object_type' => ['type' => self::TYPE_STRING, 'validate' => 'isValidObjectClassName', 'size' => 32], 'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'], 'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'], ], ]; protected static $is_present = []; /** * Send e-mail to the shop owner only if the minimal severity level has been reached. * * @param PrestaShopLogger $log */ public static function sendByMail($log) { $config_severity = (int) Configuration::get('PS_LOGS_BY_EMAIL'); if (!empty($config_severity) && $config_severity <= (int) $log->severity) { $to = array_map('trim', explode(',', Configuration::get('PS_LOGS_EMAIL_RECEIVERS'))); $language = new Language((int) Configuration::get('PS_LANG_DEFAULT')); Mail::Send( (int) Configuration::get('PS_LANG_DEFAULT'), 'log_alert', Context::getContext()->getTranslator()->trans( 'Log: You have a new alert from your shop', [], 'Emails.Subject', $language->locale ), [], $to ); } } /** * add a log item to the database and send a mail if configured for this $severity. * * @param string $message the log message * @param int $severity * @param int $errorCode * @param string $objectType * @param int $objectId * @param bool $allowDuplicate if set to true, can log several time the same information (not recommended) * * @return bool true if succeed */ public static function addLog($message, $severity = 1, $errorCode = null, $objectType = null, $objectId = null, $allowDuplicate = false, $idEmployee = null) { // Not all logs are relevant in DB so we filter them based on the configuration PS_MIN_LOGGER_LEVEL_IN_DB if ($severity < self::getMinimumLevelInDB()) { return false; } $log = new PrestaShopLogger(); $log->severity = (int) $severity; $log->error_code = (int) $errorCode; $log->message = $message; $log->date_add = date('Y-m-d H:i:s'); $log->date_upd = date('Y-m-d H:i:s'); $context = Context::getContext(); if ($idEmployee === null && isset($context->employee->id)) { $idEmployee = $context->employee->id; } if ($idEmployee !== null) { $log->id_employee = (int) $idEmployee; } if (!empty($objectType)) { $log->object_type = $objectType; if (!empty($objectId)) { $log->object_id = (int) $objectId; } } $log->id_lang = $context->language ? (int) $context->language->id : null; $log->in_all_shops = Shop::getContext() == Shop::CONTEXT_ALL; $log->id_shop = Shop::getContext() == Shop::CONTEXT_SHOP ? (int) $context->shop->getContextualShopId() : null; $log->id_shop_group = Shop::getContext() == Shop::CONTEXT_GROUP ? (int) $context->shop->getContextShopGroupID() : null; if ($objectType != 'MailerMessage') { PrestaShopLogger::sendByMail($log); } if ($allowDuplicate || !$log->isPresent()) { $res = $log->add(); if ($res) { self::$is_present[$log->getHash()] = isset(self::$is_present[$log->getHash()]) ? self::$is_present[$log->getHash()] + 1 : 1; return true; } } return false; } /** * @return string hash */ public function getHash() { if (empty($this->hash)) { $this->hash = md5( $this->message . $this->severity . $this->error_code . $this->object_type . $this->object_id . $this->id_shop . $this->id_shop_group . $this->id_lang . $this->in_all_shops ); } return $this->hash; } public static function eraseAllLogs() { return Db::getInstance()->execute('TRUNCATE TABLE ' . _DB_PREFIX_ . 'log'); } /** * check if this log message already exists in database. * * @return bool true if exists */ protected function isPresent() { if (!isset(self::$is_present[md5($this->message)])) { self::$is_present[$this->getHash()] = Db::getInstance()->getValue( (new DbQuery()) ->select('COUNT(*)') ->from('log', 'l') ->where('message = "' . pSQL($this->message) . '"') ->where('severity = ' . (int) $this->severity) ->where('error_code = ' . (int) $this->error_code) ->where('object_type = "' . pSQL($this->object_type) . '"') ->where('object_id = ' . (int) $this->object_id) ->where('id_shop = ' . (int) $this->id_shop) ->where('id_shop_group = ' . (int) $this->id_shop_group) ->where('id_lang = ' . (int) $this->id_lang) ->where('in_all_shops = ' . (int) $this->in_all_shops) ); } return self::$is_present[$this->getHash()]; } protected static function getMinimumLevelInDB(): int { if (!isset(self::$minLevelInDb)) { try { self::$minLevelInDb = (int) Configuration::get('PS_MIN_LOGGER_LEVEL_IN_DB', null, null, null, self::LOG_SEVERITY_LEVEL_INFORMATIVE); } catch (Throwable) { self::$minLevelInDb = self::LOG_SEVERITY_LEVEL_INFORMATIVE; } } return self::$minLevelInDb; } }